1 Introduction

These notes provide a comprehensive mathematical characterization of hypothesis testing, covering assumptions, procedures, types, performance measures, error types, and practical applications with manual calculations and R verification.

2 What Is Hypothesis Testing

Definition: Hypothesis testing is a formal statistical procedure used to evaluate competing claims about a population parameter or distribution based on sample data. It follows a structured, probabilistic framework to determine whether observed data provide sufficient evidence to reject a default assumption (null hypothesis) in favor of an alternative claim.

Mathematically, hypothesis testing is a decision rule that maps sample outcomes to one of two actions: “reject Ho” or “fail to reject Ho,” while controlling the long-run frequency of incorrect decisions.

2.1 The Logic of Hypothesis Testing

To provide an objective, reproducible standard for evaluating whether observed patterns in data are likely due to chance or represent genuine effects in the population.

An analogy: Statistical hypothesis testing vs medical diagnostics

Steps Statistical Hypothesis Testing Medical Diagnostics
Formulate Hypotheses Ho: No effect vs Ha: Effect exists Ho: Healthy vs Ha: Has disease
Choose Test & Threshold Select a test with \(\alpha\)=0.05 Choose related clinical tests
Collect Evidence and Aggregation Gather sample data and Compute test statistic from data Perform diagnostic test and aggregate lab result value
Make Decision Reject Ho if evidence strong enough (check if \(p \le 0.05\)) Diagnose disease if test positive (check if result exceeds diagnostic cutoff)

We can observe that the logical reasoning behind statistical hypothesis testing and medical diagnostics is identical. To better understand the hypothesis testing process, we will examine the following non-numerical examples.

Medical Example: COVID-19 Testing - Scenario: Testing for COVID infection

Step 1: Ho: Patient is not infected (healthy) v.s. Ha: Patient is infected (sick).

Step 2: Choose an appropriate COVID test based on the quality. For example, looking for the test with high specificity and sensitivity. Note: Specificity = P(T - | No COVID) and Sensitivity = P(T + | COVID).

Step 3: Wait for the test results

Step 4: Comparison and decision: If the test results falls in critical region, Reject Ho \(\Rightarrow\) diagnose COVID.

2.2 Assumptions and Step for Hypothesis Testing

Every procedure for statistical inference involves certain explicit and implicit assumptions. A family of related procedures shares a core set of common assumptions. As a major family, hypothesis testing encompasses different test types. The assumptions discussed next are common to many tests within this family, aside from those unique to a specific test.

2.2.1 Some Common Assumptions

  • Data Structure Assumptions
    • Most tests require Independence of Observations for Critical for probability calculations and standard error estimation.
    • All tests require Random Sampling so that
      • Data represent a random sample from the population
      • No systematic selection bias
      • Ensures generalizability of results
  • Measurement & Scale Assumptions
    • Reliable Measurement means that
      • Variables are measured without systematic error
      • Measurement instruments are valid and reliable
      • Random measurement error is normally distributed
  • Statistical Model Assumptions
    • Distributional Assumptions include
    • For Parametric Tests, a specific distribution assumed (e.g., normality for t-tests).
    • For non-parametric tests, fewer distributional requirements but often assume: continuity, symmetry, and identical shape across groups, etc.
    • Homogeneity Assumptions
      • Homogeneity of Variance (Homoscedasticity) is required for tests related to the regression modeling.
      • Homogeneity of Covariance is commonly required for multivariate tests in the multivariate regression modeling.
  • Inferential Assumptions
    • Sample Size Requirements reflect the amount of information in the data set
      • Sufficient Sample Size for applying Central Limit Theorem (CLT), power calculation, etc.
      • Adequate Cell Sizes (for categorical tests) for validity of tests.
    • Linearity Assumptions are required for regression related tests.

3 Formal Hypothesis Testing

This section focus on systematic introduction to hypothesis testing: logical steps, fundamental components, performance assessment.

3.1 Logical Steps

Hypothesis testing follows the basic logical process which is utilized in software development. We will use some examples from introductory statistics to explain these basic steps. As a guideline, I summarize the process into the following 6 steps:

Step 1: Gather Available Information for Hypothesis Testing: Information on sample size, the test type (right-tailed, left-tailed, and two-tailed) based on the research/practical question, significance level, etc.

Step 2: State the Hypotheses: Formally define the competing claims.

  • Null Hypothesis (\(H_0\)): The hypothesis of “no effect,” “no difference,” or “status quo.” It is assumed true until evidence suggests otherwise. It must contain a condition of equality (\(=\), \(\leq\), \(\geq\)). This means that the claimed value is attainable under the null hypothesis!
    • Example: \(H_0: \mu = \mu_0\) (The population mean \(\mu\) equals a specific value \(\mu_0\))
  • Alternative Hypothesis (\(H_1\) or \(H_a\)): The hypothesis you hope to support. It contradicts \(H_0\) and represents a “new effect” or “difference.” It is defined by the research question (\(<\), \(>\), or \(\neq\)).
    • Examples:
      • \(H_1: \mu > \mu_0\) (Right-tailed test)
      • \(H_1: \mu < \mu_0\) (Left-tailed test)
      • \(H_1: \mu \neq \mu_0\) (Two-tailed test)

Step 3: Select An Appropriate Tests Based on Given Information and Evaluate the Test Statistic

  • This is a standardized value that measures the distance between the sample statistic and the hypothesized parameter under \(H_0\). For example, in introductory statistics
    • One-sample z-test: \[ z = \frac{\bar{x} - \mu_0}{\sigma/\sqrt{n}} \]
    • One-sample t-test: \[ t = \frac{\bar{x} - \mu_0}{s/\sqrt{n}} \]
    • Chi-square test: \[ \chi^2 = \sum \frac{(O_i - E_i)^2}{E_i} \]

Step 4: Determine the Critical Value(s) and/or P-value: Two main approaches (they are conceptually linked) and both approaches requires the information about the type of the test as illustrated in the alternative hypothesis.

  • Critical Value Approach: Find the threshold value(s) from the statistical distribution (e.g., \(z_{\alpha}\), \(t_{\alpha, df}\)) that correspond to the significance level \(\alpha\) and the test type (right-tailed, left-tailed, or teo-tailed test).

  • P-value Approach: Calculate the p-value—the probability of obtaining a test statistic at least as extreme as the one observed, assuming \(H_0\) is true.

Step 5: Make a Decision: Compare your result from Step 3 to the test statistic or the given significant level. Crucial Note: You never “accept” \(H_0\). You either reject it or fail to reject it. Failing to reject means there is insufficient evidence against \(H_0\), not proof that it is true.

  • Using Critical Values: If |test statistic| > |critical value| \(\Rightarrow\) Reject \(H_0\); otherwise, Conclude \(H_0\).

  • Using P-value: If p-value \(\le \alpha\) \(\Rightarrow\) Reject \(H_0\); If p-value \(> \alpha\) \(\Rightarrow\) Fail to Reject \(H_0\).

Step 6: State the Conclusion in Context: Translate the statistical decision into a clear, plain-language statement about the research question.

  • If you reject \(H_0\): There is sufficient statistical evidence at the \(\alpha\) level to conclude that [state \(H_1\) in context]. For example, There is sufficient evidence (\(\alpha=0.05\)) to conclude that the new drug lowers blood pressure more than the placebo.”

  • If you fail to reject \(H_0\): “There is insufficient statistical evidence at the \(\alpha\) level to conclude that [state \(H_1\) in context].” For example: There is insufficient evidence (\(\alpha=0.05\)) to conclude that the new manufacturing process changes the product’s strength.”


3.2 Sampling Distribution of Test Statistic

One of the critical steps in the logical process above is to find the critical value or p-value to make a decision. Both are dependent on the distribution of the test statistic, more specifically, the sampling distribution of the test statistic. In fact, a test statistic is essentially a pivotal quantity whose distribution is independent of the parameters. We can see this pattern in the examples in Step 3 of the logical process for hypothesis testing.

Exact Pivotal Quantity - While exact pivotal quantity is not a formal textbook term, it emphasizes the property that a function of the sample and the true parameter has a fully specified, exact sampling distribution (standard normal, t, chi‑square, etc.), which is pivotal for exact inference.

Asymptotic pivotal quantity - The name itself conveys the key property: it is a quantity (a function of the data and the parameter) whose distribution converges to a fixed, known form (such as standard normal) as the sample size grows to infinity. This means, the sampling distribution is only an approximation. Most likelihood based hypothesis tests eventually define an asymptotic pivotal quantity to approximate a fixed sampling distribution independent on parameters and sample data.

We will discuss asymptotic hypothesis testing based on the likelihood in the next module.

3.3 P-value and P-Hacking

The mathematical definition of the p‑value involves conditional probability and is not easy to grasp. An informal definition, given in an American Statistical Association (ASA) statement, reads:

“Informally, a p‑value is the probability, under a specified statistical model, that a statistical summary of the data would be equal to or more extreme than its observed value.”

3.4 Goodness (Badness) of Tests

This is a fundamental concept in statistics. Here’s a clear breakdown of performance measures and error types in hypothesis testing, framed around the classic confusion matrix for a binary test (Ho vs. Ha). Most of the performance measures are defined based on the following confusion matrix.

A. Decision (Confusion) Matrix

Comments: Several practically important facts about the confusion matrix for hypothesis testing:

  • The conditional probabilities \(\alpha\) and \(\beta\) (see the mathematical definitions below) are not estimable based on a single data set since we don’t know TRUE status of null and alternative hypotheses. In other words, the confusion matrix for hypothesis testing represents potential outcomes under different states of nature, not actual observed proportions.

  • Similar to the interpretation of a \(100(1-\alpha)\%\) confidence interval: if we were to take 100 random samples of the same size using the same sampling protocol, and construct 100 confidence intervals at that level, we would expect about \(100(1-\alpha)\) of those intervals to contain the true parameter value. The confusion matrix in hypothesis testing also describes long‑run hypothetical outcomes. It illustrates:

    • What would happen if we repeated the same experiment many times,
    • Conditional on either Ho always being true (the left column) or Ha always being true (the right column).
  • The parallel frequentist interpretations at \(\alpha = 0.05\)

    • Confidence Interval: If we constructed 100 confidence intervals from 100 independent samples, we’d expect about 95 to contain the true parameter value.
    • Hypothesis Testing (Confusion Matrix): (I) If we performed 100 hypothesis tests when Ho is true, we’d expect about 5 Type I errors [false positives] AND (II) If we performed 100 hypothesis tests when Ha is true with effect size \(\delta\), we’d expect about \((1-\alpha)×100\) correct rejections [true positives].
  • p-value, significant level, and type I error rate: These three concepts form the core decision-making framework of frequentist statistics.

    • Significance Level (\(\alpha\)) is a threshold (design parameter) for decision-making and determined before data collection.
    • p-value is a data-dependent measure of evidence strength calculated from data after data collection.
    • Type I Error Probability is the risk of false positive based on Long-run frequency. It is determined conceptually before or after data collection.

B. Mathematical Definitions

Most of the test performance are defined in the form of conditional probabilities. They can be estimated based on the observed confusion matrix defined above.

  • Type I Error (\(\alpha\)):

\[ \alpha = P(\text{Reject } H_0 \mid H_0 \text{ true}) \]

  • Type II Error (\(\beta\)):

\[ \beta = P(\text{Fail to reject } H_0 \mid H_1 \text{ true}) \]

  • Power (\(1-\beta\)):

\[ \text{Power} = P(\text{Reject } H_0 \mid H_1 \text{ true}) = 1 - \beta \]

The measures above assess performance locally, meaning that the power reflects the specific value claimed in the hypothesis. Generally, we use power to compare the performance (goodness or badness) of two or more tests.

If we free the claimed value in the hypothesis, we then turn the local performance measures into global measures. For example, we can define the power function as follows:

  • Power Function: Assume the claimed value in the hypothesis is an unknown parameter \(\theta\). This means the power of the test depends on the choice of \(\theta\). Therefore, we can define the power function as:

\[ \pi(\theta) = P(\text{Reject } H_0 \mid \theta) \]

4 How Hypothesis Testing is Applied in Clinical Trials

Hypothesis testing is not just used in clinical trials—it is the mandatory, formal statistical methodology that underpins the entire FDA drug approval process. It provides an objective, quantitative standard for deciding whether the evidence of a drug’s efficacy is strong enough to warrant making it available to patients, all while controlling the risk of false claims. The process is a sequential application of hypothesis tests, with each phase addressing more definitive questions under increasingly stringent statistical controls.

This section outlines the key stages of confirmatory clinical trials, highlighting the use of hypothesis testing in each phase.

4.1 Stages of Clinical Trials

Clinical trials are conducted in a series of phased steps, each designed to answer specific questions about a new medical intervention’s safety, efficacy, and appropriate use. Here is a standard outline of the stages.

Additional Key Stage (Pre-Trial)

  • Preclinical Research: Before human testing begins, laboratory (in vitro - outside living organism) and animal (in vivo - in living organism) studies are conducted to gather preliminary efficacy, toxicity, and pharmacokinetic information. This is not considered a “clinical” phase, as it does not involve human participants.

The sponsor submits an Investigational New Drug (IND) application with pre-clinical data, manufacturing info, and the Phase 1 study plan, requiring FDA approval to start human trials.


Phase 1: Safety & Dosage - an initial exploratory stage. Data on safety and dosage is submitted, and the FDA must permit the trial to advance to Phase 2 if results are favorable.

  • Primary Goal: Assess the safety, tolerability, and pharmacokinetics (how the body processes the drug) in a small group (20-100).

  • Participants: Usually healthy volunteers, though for serious conditions (e.g., cancer), participants may be patients.

  • Key Focus: Determine a safe dosage range and identify common side effects.

Phase 2: Efficacy & Side Effects - an exploratory stage. Efficacy and side effects are assessed; positive findings allow progression to Phase 3.

  • Primary Goal: Evaluate the intervention’s preliminary efficacy and further assess its safety.

  • Participants: A larger group (up to several hundred) of patients with the target disease or condition.

  • Key Focus: Gather data on whether the drug works (e.g., shrinks tumors, lowers blood pressure) and monitor short-term side effects. This phase often explores different dosing regimens.

Phase 3: Confirmatory & Monitoring - a confirmatory stage. After large-scale trials confirm effectiveness and safety, the sponsor submits a New Drug Application (NDA) for FDA review and approval to market the drug.

  • Primary Goal: Confirm effectiveness, monitor long-term side effects, and compare the new intervention to the current standard treatment.

  • Participants: Large groups (300 to 3,000+ patients) across multiple research centers.

  • Key Focus: Provide the definitive evidence of benefit and risk required for regulatory approval (e.g., by the FDA). This is the confirmatory stage where hypothesis testing is formally applied to prove efficacy.

Regulatory Review and Approval

  • After Phase 3, all data are compiled and submitted to regulatory authorities (e.g., FDA, EMA) for review and a decision on marketing approval.

Phase 4: Post-Marketing Surveillance - Ongoing monitoring for long-term effects occurs after the drug is on the market.

  • Primary Goal: Monitor the drug’s long-term safety, effectiveness, and optimal use in the general population.

  • Participants: Thousands of patients in real-world settings after the drug is publicly available.

  • Key Focus: Detect rare or long-term adverse effects and study new populations or uses.

4.2 When and How Hypothesis Testing Is Used

The use of hypothesis testing in Phase I and Phase II trials is fundamentally different from its role in Phase III. The primary goals are safety, dosing, and estimating effects—not confirming them with statistical rigor.

  • Phase I: Hypothesis testing is minimal. The focus is on estimation and safety.

  • Phase II: Hypothesis testing is a critical decision-making tool but is applied with exploratory intent. A positive result is a signal to move forward, not a claim for approval.

  • Phase III: Hypothesis testing is the pre-specified, rigorous experiment designed to confirm the definitive hypothesis for regulators.

In terms of statistical role and rigor, hypothesis testing in Phase I/II trials is flexible, with the Type I error rate (\(\alpha\)) often not strictly controlled. In other words, it is an informal tool used primarily for internal decision-making and signal detection. In contrast, hypothesis testing in Phase III is strict: the Type I error (\(\alpha\)) is strongly controlled. It is a formal, mandatory, and definitive process used to confirm efficacy and safety for regulatory approval.

To outline of overarching framework of rigorous hypothesis testing, we use focus on its application in phase III trial. We know that all confirmatory clinical trials are designed as controlled experiments with:

  • A pre-specified primary outcome (e.g., tumor size reduction, survival time, symptom score).

  • A null hypothesis (Ho) that the new treatment is no better than the control (placebo or standard of care).

  • An alternative hypothesis (Ha) that the new treatment is better.

  • A pre-defined significance level (\(\alpha\)), almost always \(\alpha = 0.05\) for the primary endpoint.

  • A pre-specified statistical test (t-test, log-rank test, chi-square, etc.) and analysis plan.

Comment: In the context of confirmatory clinical trials, the pre-defined significance level (alpha, \(\alpha\)) and Type I error are intimately related but distinct concepts. In the simplest fixed design: By setting \(\alpha = 0.05\), you are designing the trial to have a maximum allowable Type I error rate of 5%. In other words, if you follow the statistical plan exactly, the actual probability of making a Type I error (falsely rejecting the null) is controlled at 0.05.

5 Illustrative Examples

This section uses two simple tests about populations to illustrate the steps suggested for hypothesis testing.

5.1 Example 1: One-Sample t-test

Problem: A company claims their energy drink increases IQ (\(\mu = 100\)). Sample of 25 users has mean IQ = 106, SD = 15. Test at \(\alpha = 0.05\).

Manual Calculation:

  • Step 1: The information is clearly given in the problem. \(n = 25, \bar{x} = 106, s = 15, \mu_0 = 100\), and \(\alpha = 0.05\). The claim (increase IQ) is that \(\mu > 100\)

  • Step 2: Hypotheses

    • \(H_0: \mu = 100\) (no effect)
    • \(H_1: \mu > 100\) (one-tailed, drink increases IQ)
  • Step 3: Test Statistic

\[n = 25, \bar{x} = 106, s = 15, \mu_0 = 100\] \[t = \frac{106 - 100}{15/\sqrt{25}} = \frac{6}{15/5} = \frac{6}{3} = 2.0\]

\[df = n - 1 = 24\]

  • Step 4: Critical Value for this right-tailed test is

\[t_{\alpha=0.05, df=24} = 1.711\]

  • Step 5: Decision - since \(t = 2.0 > 1.711\), reject \(H_0\).

  • Step 6: Interpretation - Evidence suggests drink increases IQ.

Verification Using R:

# One-sample t-test in R
set.seed(123)
simulated_iq <- rnorm(25, mean = 106, sd = 15)
result <- t.test(simulated_iq, mu = 100, 
                 alternative = "greater")

# Output
print(result)

    One Sample t-test

data:  simulated_iq
t = 1.9365, df = 24, p-value = 0.03233
alternative hypothesis: true mean is greater than 100
95 percent confidence interval:
 100.6408      Inf
sample estimates:
mean of x 
    105.5 
###
cat("\nManual t-value: 2.0",
    "\nR t-value:", round(result$statistic, 3),
    "\nCritical t-value (0.05): 1.711",
    "\nR p-value:", round(result$p.value, 4))

Manual t-value: 2.0 
R t-value: 1.937 
Critical t-value (0.05): 1.711 
R p-value: 0.0323


5.2 Example 2: Two-Sample t-test

Problem: Compare exam scores for two teaching methods with the following give information:

  • Method A: \(n_1=30\), \(\bar{x}_1=78\), \(s_1=8\)
  • Method B: \(n_2=35\), \(\bar{x}_2=72\), \(s_2=10\)
  • Test at \(\alpha=0.05\) if methods differ.

Manual Calculation:

  • Step 1: The given information is clearly listed above. The claim is \(\mu_1 -\mu_2 \ne 0\)

  • Step 2: Hypotheses

    • \(H_0: \mu_1 = \mu_2\)
    • \(H_1: \mu_1 \neq \mu_2\)
  • Step 3: Pooled Variance

\[s_p^2 = \frac{(n_1-1)s_1^2 + (n_2-1)s_2^2}{n_1+n_2-2}\]

\[= \frac{(29)(64) + (34)(100)}{63}\] \[= \frac{1856 + 3400}{63} = \frac{5256}{63} = 83.43\]

\[s_p = \sqrt{83.43} = 9.134\]

  • Step 4: Test Statistic

\[t = \frac{\bar{x}_1 - \bar{x}_2}{s_p\sqrt{\frac{1}{n_1} + \frac{1}{n_2}}}\] \[= \frac{78 - 72}{9.134\sqrt{\frac{1}{30} + \frac{1}{35}}}\] \[= \frac{6}{9.134\sqrt{0.0333 + 0.0286}}\]

\[= \frac{6}{9.134\sqrt{0.0619}}\]

\[= \frac{6}{9.134 \times 0.2488} = \frac{6}{2.273} = 2.639\]

\[df = n_1 + n_2 - 2 = 63\]

  • Step 5: Critical Value for this two-tailed test

\[t_{\alpha=0.05,df=63} \approx 2.000\]

  • Step 6: Decision - Since \(|t| = 2.639 > 2.000\), reject \(H_0\)

Verification Using R

# Two-sample t-test in R
set.seed(123)
method_A <- rnorm(30, mean = 78, sd = 8)
method_B <- rnorm(35, mean = 72, sd = 10)

# Equal variance assumed
result <- t.test(method_A, method_B, 
                 var.equal = TRUE,
                 alternative = "two.sided")

print(result)

    Two Sample t-test

data:  method_A and method_B
t = 2.3876, df = 63, p-value = 0.01997
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 0.7861114 8.8580044
sample estimates:
mean of x mean of y 
 77.62317  72.80111 

6 Power Analysis

Effect size, statistical power, and sample size determination form the statistical trinity for designing robust experiments and studies. We will first briefly outline the components of this trinity before presenting an example.

6.1 Effect Size

Effect Size is a quantitative measure of the magnitude of the phenomenon or difference you are studying. It’s a standardized, scale-free metric that answers “how much?” rather than just “is there an effect?”. While statistical significance (p-values) answers “Is there an effect?”, effect size answers “How large is the effect?”

In other words, effect size quantifies the magnitude of practical importance and p-value measures the statistical significance.


The effect size is defined differently according to the actual tests. Some common types are listed below:

  • For Differences between Groups: Cohen’s d (mean difference / pooled standard deviation \(=(\mu_1-\mu_2)/\sigma\)). Small ~0.2, Medium ~0.5, Large ~0.8.

  • For Associations: Pearson’s r (correlation). Small ~0.1, Medium ~0.3, Large ~0.5.

  • For Proportions: Risk difference, odds ratio, risk ratio. These important measure will be discussed in subsequent courses

  • For Variance Explained: \(R^2\),.


Key Principle: We must specify a Minimum Clinically/Practically Important Effect. This is the smallest effect that would be meaningful in real-world context. It’s not a statistical choice, but a subject-matter one.

6.2 Statistical Power

As discussed earlier, the probability that our test will correctly reject the null hypothesis (e.g, there is no treatment effect) when the alternative hypothesis (there is treatment effect) is true. In other words, the power is the probability of detect the true treatment effect.

  • \(\text{Power} = P(\text{Reject Ho} | \text{Ha}) = 1 - P(\text{Conclude Ho}|\text{Ha}) = 1 - \beta\), where \(\beta = P(\text{Conclude Ho}|\text{Ha})\) is the Type II error rate (false negative rate).

  • Convention: A common target is 80% power (\(\beta\) = 0.20). For more sensitive or high-stakes studies, 90% is often used.

In plain English: For a preset effect size, power is the chance the sample (based on an experiment) will successfully detect it. Low power means the study has a low chance of finding a real effect, even if one exists.

6.3 Sample Size Determination

Sample Size Determination is the process of calculating the number of participants or observations needed in a study to achieve a specified power for a given effect size and significance level. Sample size determination is the foundation of rigorous clinical research. It ensures studies are properly sized to detect meaningful effects without exposing participants to unnecessary risk or wasting resources.

It’s calculating “How many people do we need to test to have a good chance of proving our treatment works, assuming it actually works as well as we hope?”

The general logical process for determine the sample size at a given significant level (\(\alpha\)) is to

  • start with the smallest effect (size) that matters;
  • decide the power (i.e., how sure we need to be able to detect the effect);
  • calculate the sample size required.

6.4 The Trinity Relationship

The trinity relationship refers to the fundamental interdependence among effect size, statistical power, and sample size in hypothesis testing. Once we fix any two of these, the third is essentially determined (given a significance level \(\alpha\) and a test/model).

The next few bullet points explain how the three components interact. To facilitate understanding, we use animated figures based on one-sample test of a normal population mean with know population standard deviation \(\sigma\):

\[ H_0: \mu \le \mu_0 \quad \text{v.s.} \quad H_a: \mu > \mu_0 \] The effect size is \((\mu - \mu_0)/(\sigma/\sqrt{n})\) and the test statistic \(T=(\bar{x}-\mu_0)/(\sigma/\sqrt{n})\).

  • Effect Size \(\Longleftrightarrow\) Sample Size
    • Caution: Effect size is independent of sample size. However, it impacts the power to detect the effect size. To be more specific, larger sample sizes increase the power to detect a given effect size, while smaller sample sizes reduce it.
      • Smaller effect \(\Rightarrow\) larger sample needed
      • Larger effect \(\Rightarrow\) smaller sample sufficient
    • Detecting a tiny effect requires a lot of data.
  • Sample Size \(\Longleftrightarrow\) Power
    • Larger sample sizes reduce the denominator in the test statistic, which decreases the variance of the sampling distributions under \(H_0\) and \(H_a\) (i.e., the density curves become narrower). This in turn increases power.
      • Larger sample \(\Rightarrow\) higher power
      • Smaller sample \(\Rightarrow\) lower power
    • Power increases monotonically with n.

  • Effect Size \(\Longleftrightarrow\) Power
    • Larger effect \(\Rightarrow\) higher power (for fixed n)
    • Smaller effect \(\Rightarrow\) lower power
    • Stronger signals are easier to detect.

6.5 Power Calculation

The noncentrality parameter (NCP) is a standardized measure of how far the alternative hypothesis (\(H_a\)) is from the null hypothesis (\(H_0\)) in terms of standard errors of the corresponding sample statistics. The actual formula of NCP is dependent on the specific test. The following are few NCPs for tests that commonly used in power analysis

  • One-sample t-test: \(H_0:\) \(\mu = \mu_0\) vs \(H_a:\) \(\mu \ne (>, <) \quad\mu_0\)
    • Standard error of sample statistic \(\bar{x}\) is \(\sigma/\sqrt{n}\)
    • Difference between \(H_a\) and \(H_0\): \(\delta = \mu - \mu_0\);
    • The NCP is defined by

\[ \lambda = \frac{\mu - \mu_0}{\sigma/\sqrt{n}} \quad \text{this is differs the test statistic} \quad T = \frac{\bar{x}-\mu_0}{s/\sqrt{n}}. \]

  • Two-sample t-test: \(H_0\): \(\mu_1 - \mu_2 = 0\) vs \(H_a\): \(\mu_1 - \mu_2 \ne (>, <) \quad 0\), both population variances are summed to be equal.
    • Standard error of sample statistic \(\bar{x}_1 - \bar{x}_2\) based on the pooled sample is \(\sigma_p/\sqrt{1/n_1+1/n_2}\)
    • Difference between \(H_a\) and \(H_0\): \(\delta = (\mu_1 - \mu_2)-0 = \mu_1 - \mu_2\);
    • The NCP is defined by

\[ \lambda = \frac{\delta}{\sigma/\sqrt{1/n_1+1/n_2}} \quad \text{this is differs the test statistic} \quad T = \frac{\bar{x}_1-\bar{x}_2}{s_p/\sqrt{1/n_1+1/n_2}}. \]

We will not list the noncentrality parameters (NCPs) for other tests for now. The key takeaway is to apply the definition of the NCP to the specific distribution in order to derive the corresponding NCP formula. Next, we use the one-sample t-test as an example to derive the power formula.

Consider one-sample two-sided t-test:

\[ H_0: \mu = \mu_0, \qquad H_1: \mu \neq \mu_0 \quad (\text{two-sided}) \]

The test statistic

\[ T = \frac{\bar{X} - \mu_0}{S/\sqrt{n}} \]

Effect size (Cohen’s \(d\) for one sample):

\[ \delta = \frac{\mu_1 - \mu_0}{\sigma} \]

Under \(H_a\), \(T\) follows a non-central \(t\)-distribution with \(n-1\) degrees of freedom and non-centrality parameter:

\[ \lambda = \sqrt{n}\,\delta = \sqrt{n} \cdot \frac{\mu_1 - \mu_0}{\sigma} = \frac{\mu_1 - \mu_0}{\sigma/\sqrt{n} } \]

For significance level \(\alpha\):

\[ \text{Reject } H_0 \text{ if } |T| > t_{1-\alpha/2,\, n-1} \]

where \(t_{1-\alpha/2,\, n-1}\) is the \(1-\alpha/2\) quantile of the central \(t\)-distribution with \(n-1\) df.

Let \(F_{t_{n-1}(\lambda)}(\cdot)\) denote the CDF of the non-central \(t\)-distribution with df \(n-1\) and NCP \(\lambda\). Then:

\[ \boxed{\text{Power} = 1 - F_{t_{n-1}(\lambda)}\bigl(t_{1-\alpha/2,\, n-1}\bigr) + F_{t_{n-1}(\lambda)}\bigl(-t_{1-\alpha/2,\, n-1}\bigr)} \]

The above figure shows that, for a two-tailed t-test, the power is the two tail areas (shaded region in dark red) of non-central t-distribution defined by the two critical values under the regular t-distribution under \(H_0\).

In R, we only need to provide the value of the non-centrality parameter ncp for find the tail areas and other related values as well.

The formula for sample size determination is a recursive equation which is not easy to use in manual calculation. We can approximate using z-scores in the following

\[ n \approx\left( \frac{(z_{1-\alpha/2} - z_{1-\beta})\sigma}{\delta}\right)^2. \]

Power Calculation in Numerical Example using R function power.t.test() and manual calculation respectively.

Consider the following one-sample two-tailed test:

\[ H_0: \mu = 100, \qquad H_1: \mu \neq 100 \quad (\text{e.g.} \quad \mu = 106)\quad (\text{two-sided}) \]

and the following given information

\[ n = 25, \alpha = 0.05, \sigma = 15, \text{ two-tailed test} \]

\[ \lambda= \frac{106 - 100}{15/\sqrt{25}} = \frac{6}{3} = 2 \quad \text{ and } \quad \delta = 106-100 = 6. \]

Using power tables or software: Power \(\approx\) 0.80

Power Calculation Using R

# Power calculation for one-sample t-test
power_calc <- power.t.test(n = 25, 
                          delta = 6,    # true difference between the means in H0 and Ha
                          sd = 15,      
                          sig.level = 0.05,
                          type = "one.sample",
                          alternative = "two.sided")
print(power_calc)

     One-sample t test power calculation 

              n = 25
          delta = 6
             sd = 15
      sig.level = 0.05
          power = 0.4839669
    alternative = two.sided
# Sample size calculation
sample_size <- power.t.test(power = 0.90, 
                            delta = 6,
                           sd = 15,
                           sig.level = 0.05,
                           type = "one.sample",
                           alternative = "two.sided")
cat("\nRequired sample size for 90% power:", ceiling(sample_size$n))

Required sample size for 90% power: 68

Manual Calculation - using R as a calculator and the base t and Z distributions in base R library.

# given info
n = 25
power = 0.90
sig = 15
delta = 6
lambda = 2
sig.level = 0.05
##
crit = qt(0.975, n-1)
##
power = 1-pt(crit, df = 24, ncp = lambda) + pt(-crit, df = 24, ncp = lambda)
n =((qnorm(0.975)-qnorm(0.10))*sig/delta)^2 
data.frame(cbind(power = power, n = n))
      power        n
1 0.4840183 65.67139

Manual calculation and power.t.test() yield the same results, but manual calculation results in a relatively conservative sample size.

LS0tDQp0aXRsZTogIkZ1bmRhbWVudGFscyBvZiBIeXBvdGhlc2lzIFRlc3RpbmcgYW5kIFBvd2VyIEFuYWx5c2lzIg0KYXV0aG9yOiAiQ2hlbmcgUGVuZyINCmRhdGU6ICJXZXN0IENoZXN0ZXIgVW5pdmVyc2l0eSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdG9jX2NvbGxhcHNlZDogeWVzDQogICAgY29kZV9mb2xkaW5nOiBzaG93DQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgc21vb3RoX3Njcm9sbDogeWVzDQogICAgdGhlbWU6IGx1bWVuDQogIHBkZl9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICBmaWdfd2lkdGg6IDMNCiAgICBmaWdfaGVpZ2h0OiAzDQogIHdvcmRfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgZmlnX2NhcHRpb246IHllcw0KICAgIGtlZXBfbWQ6IHllcw0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lDQotLS0NCg0KYGBge2NzcywgZWNobyA9IEZBTFNFfQ0KI1RPQzo6YmVmb3JlIHsNCiAgY29udGVudDogIlRhYmxlIG9mIENvbnRlbnRzIjsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtc2l6ZTogMS4yZW07DQogIGRpc3BsYXk6IGJsb2NrOw0KICBjb2xvcjogbmF2eTsNCiAgbWFyZ2luLWJvdHRvbTogMTBweDsNCn0NCg0KDQpkaXYjVE9DIGxpIHsgICAgIC8qIHRhYmxlIG9mIGNvbnRlbnQgICovDQogICAgbGlzdC1zdHlsZTp1cHBlci1yb21hbjsNCiAgICBiYWNrZ3JvdW5kLWltYWdlOm5vbmU7DQogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOjA7DQp9DQoNCmgxLnRpdGxlIHsgICAgLyogbGV2ZWwgMSBoZWFkZXIgb2YgdGl0bGUgICovDQogIGZvbnQtc2l6ZTogMjJweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQogIGZvbnQtZmFtaWx5OiAiR2lsbCBTYW5zIiwgc2Fucy1zZXJpZjsNCn0NCg0KaDQuYXV0aG9yIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxNXB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6IHN5c3RlbS11aTsNCiAgY29sb3I6IG5hdnk7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDQuZGF0ZSB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiAiR2lsbCBTYW5zIiwgc2Fucy1zZXJpZjsNCiAgY29sb3I6IERhcmtCbHVlOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmgxIHsgLyogSGVhZGVyIDEgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDIwcHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoMiB7IC8qIEhlYWRlciAyIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE2cHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDQgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMTRweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KLyogQWRkIGRvdHMgYWZ0ZXIgbnVtYmVyZWQgaGVhZGVycyAqLw0KLmhlYWRlci1zZWN0aW9uLW51bWJlcjo6YWZ0ZXIgew0KICBjb250ZW50OiAiLiI7DQoNCmJvZHkge2JhY2tncm91bmQtY29sb3I6ICNmZmZmZmY7DQogICAgICBjb2xvcjogIzAwMDAwMDsNCiAgICAgIGZvbnQtZmFtaWx5OiBBcmlhbCwgc2Fucy1zZXJpZjsNCiAgICAgIGZvbnQtc2l6ZTogMXJlbTsNCiAgICAgIGxpbmUtaGVpZ2h0OiAxLjY7DQogICAgICB9DQoNCi5oaWdobGlnaHRtZSB7IGJhY2tncm91bmQtY29sb3I6eWVsbG93OyB9DQoNCnAgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9DQoNCn0NCmBgYA0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMgY29kZSBjaHVuayBzcGVjaWZpZXMgd2hldGhlciB0aGUgUiBjb2RlLCB3YXJuaW5ncywgYW5kIG91dHB1dCANCiMgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgb3V0cHV0IGZpbGVzLg0KaWYgKCFyZXF1aXJlKCJrbml0ciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpDQogICBsaWJyYXJ5KGtuaXRyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJwYW5kZXIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygicGFuZGVyIikNCiAgIGxpYnJhcnkocGFuZGVyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJwc3ljaCIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInBzeWNoIikNCiAgbGlicmFyeShwc3ljaCkNCn0NCmlmICghcmVxdWlyZSgiUkNvbG9yQnJld2VyIikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygiUkNvbG9yQnJld2VyIikNCiAgbGlicmFyeShSQ29sb3JCcmV3ZXIpDQp9DQoNCmlmICghcmVxdWlyZSgiYm9vdCIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoImJvb3QiKQ0KICBsaWJyYXJ5KGJvb3QpDQp9DQppZiAoIXJlcXVpcmUoImVmZnNpemUiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJlZmZzaXplIikNCiAgbGlicmFyeShlZmZzaXplKQ0KfQ0KIyMgbGlicmFyeShlZmZzaXplKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCAgICAgICAjIGluY2x1ZGUgY29kZSBjaHVuayBpbiB0aGUgb3V0cHV0IGZpbGUNCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsICAgIyBzb21ldGltZXMsIHlvdSBjb2RlIG1heSBwcm9kdWNlIHdhcm5pbmcgbWVzc2FnZXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgeW91IGNhbiBjaG9vc2UgdG8gaW5jbHVkZSB0aGUgd2FybmluZyBtZXNzYWdlcyBpbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRoZSBvdXRwdXQgZmlsZS4gDQogICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cyA9IFRSVUUsICAgICMgeW91IGNhbiBhbHNvIGRlY2lkZSB3aGV0aGVyIHRvIGluY2x1ZGUgdGhlIG91dHB1dA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGluIHRoZSBvdXRwdXQgZmlsZS4NCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgY29tbWVudCA9IE5BDQogICAgICAgICAgICAgICAgICAgICAgKSAgDQpgYGANCg0KXA0KDQojIEludHJvZHVjdGlvbg0KDQpUaGVzZSBub3RlcyBwcm92aWRlIGEgY29tcHJlaGVuc2l2ZSBtYXRoZW1hdGljYWwgY2hhcmFjdGVyaXphdGlvbiBvZiBoeXBvdGhlc2lzIHRlc3RpbmcsIGNvdmVyaW5nIGFzc3VtcHRpb25zLCBwcm9jZWR1cmVzLCB0eXBlcywgcGVyZm9ybWFuY2UgbWVhc3VyZXMsIGVycm9yIHR5cGVzLCBhbmQgcHJhY3RpY2FsIGFwcGxpY2F0aW9ucyB3aXRoIG1hbnVhbCBjYWxjdWxhdGlvbnMgYW5kIFIgdmVyaWZpY2F0aW9uLg0KDQoNCg0KIyBXaGF0IElzIEh5cG90aGVzaXMgVGVzdGluZw0KDQoqKkRlZmluaXRpb24qKjogSHlwb3RoZXNpcyB0ZXN0aW5nIGlzIGEgZm9ybWFsIHN0YXRpc3RpY2FsIHByb2NlZHVyZSB1c2VkIHRvIGV2YWx1YXRlIGNvbXBldGluZyBjbGFpbXMgYWJvdXQgYSBwb3B1bGF0aW9uIHBhcmFtZXRlciBvciBkaXN0cmlidXRpb24gYmFzZWQgb24gc2FtcGxlIGRhdGEuIEl0IGZvbGxvd3MgYSBzdHJ1Y3R1cmVkLCBwcm9iYWJpbGlzdGljIGZyYW1ld29yayB0byBkZXRlcm1pbmUgd2hldGhlciBvYnNlcnZlZCBkYXRhIHByb3ZpZGUgc3VmZmljaWVudCBldmlkZW5jZSB0byByZWplY3QgYSBkZWZhdWx0IGFzc3VtcHRpb24gKG51bGwgaHlwb3RoZXNpcykgaW4gZmF2b3Igb2YgYW4gYWx0ZXJuYXRpdmUgY2xhaW0uDQoNCk1hdGhlbWF0aWNhbGx5LCBoeXBvdGhlc2lzIHRlc3RpbmcgaXMgYSBkZWNpc2lvbiBydWxlIHRoYXQgbWFwcyBzYW1wbGUgb3V0Y29tZXMgdG8gb25lIG9mIHR3byBhY3Rpb25zOiAicmVqZWN0IEhvIiBvciAiZmFpbCB0byByZWplY3QgSG8sIiB3aGlsZSBjb250cm9sbGluZyB0aGUgbG9uZy1ydW4gZnJlcXVlbmN5IG9mIGluY29ycmVjdCBkZWNpc2lvbnMuDQoNCg0KIyMgVGhlIExvZ2ljIG9mIEh5cG90aGVzaXMgVGVzdGluZw0KDQpUbyBwcm92aWRlIGFuIG9iamVjdGl2ZSwgcmVwcm9kdWNpYmxlIHN0YW5kYXJkIGZvciBldmFsdWF0aW5nIHdoZXRoZXIgb2JzZXJ2ZWQgcGF0dGVybnMgaW4gZGF0YSBhcmUgbGlrZWx5IGR1ZSB0byBjaGFuY2Ugb3IgcmVwcmVzZW50IGdlbnVpbmUgZWZmZWN0cyBpbiB0aGUgcG9wdWxhdGlvbi4NCg0KDQoqKkFuIGFuYWxvZ3kqKjogU3RhdGlzdGljYWwgaHlwb3RoZXNpcyB0ZXN0aW5nIHZzIG1lZGljYWwgZGlhZ25vc3RpY3MNCg0KfCBTdGVwc3wgICAgICAgICoqU3RhdGlzdGljYWwgSHlwb3RoZXNpcyBUZXN0aW5nKiogICAgICB8ICAgICAgKipNZWRpY2FsIERpYWdub3N0aWNzKiogICAgICAgIHwNCnw6LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSB8Oi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXw6LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfA0KfCAqKkZvcm11bGF0ZSBIeXBvdGhlc2VzKiogfCBIbzogTm8gZWZmZWN0IHZzIEhhOiBFZmZlY3QgZXhpc3RzIHwgIEhvOiBIZWFsdGh5IHZzIEhhOiBIYXMgZGlzZWFzZSAgICB8DQp8ICoqQ2hvb3NlIFRlc3QgJiBUaHJlc2hvbGQqKiB8ICBTZWxlY3QgYSB0ZXN0IHdpdGggJFxhbHBoYSQ9MC4wNSAgICAgfCBDaG9vc2UgcmVsYXRlZCBjbGluaWNhbCB0ZXN0cyB8DQp8ICoqQ29sbGVjdCBFdmlkZW5jZSBhbmQgQWdncmVnYXRpb24qKiB8ICBHYXRoZXIgc2FtcGxlIGRhdGEgYW5kIENvbXB1dGUgdGVzdCBzdGF0aXN0aWMgZnJvbSBkYXRhIHwgUGVyZm9ybSBkaWFnbm9zdGljIHRlc3QgYW5kIGFnZ3JlZ2F0ZSBsYWIgcmVzdWx0IHZhbHVlIHwNCnwgKipNYWtlIERlY2lzaW9uKiogfCBSZWplY3QgSG8gaWYgZXZpZGVuY2Ugc3Ryb25nIGVub3VnaCAoY2hlY2sgaWYgJHAgXGxlIDAuMDUkKSB8IERpYWdub3NlIGRpc2Vhc2UgaWYgdGVzdCBwb3NpdGl2ZSAoY2hlY2sgaWYgcmVzdWx0IGV4Y2VlZHMgZGlhZ25vc3RpYyBjdXRvZmYpIHwNCg0KDQpXZSBjYW4gb2JzZXJ2ZSB0aGF0IHRoZSBsb2dpY2FsIHJlYXNvbmluZyBiZWhpbmQgc3RhdGlzdGljYWwgaHlwb3RoZXNpcyB0ZXN0aW5nIGFuZCBtZWRpY2FsIGRpYWdub3N0aWNzIGlzIGlkZW50aWNhbC4gVG8gYmV0dGVyIHVuZGVyc3RhbmQgdGhlIGh5cG90aGVzaXMgdGVzdGluZyBwcm9jZXNzLCB3ZSB3aWxsIGV4YW1pbmUgdGhlIGZvbGxvd2luZyBub24tbnVtZXJpY2FsIGV4YW1wbGVzLg0KDQoNCioqTWVkaWNhbCBFeGFtcGxlOiBDT1ZJRC0xOSBUZXN0aW5nKiogLSBTY2VuYXJpbzogVGVzdGluZyBmb3IgQ09WSUQgaW5mZWN0aW9uDQoNCioqU3RlcCAxKio6IEhvOiBQYXRpZW50IGlzIG5vdCBpbmZlY3RlZCAoaGVhbHRoeSkgdi5zLiBIYTogUGF0aWVudCBpcyBpbmZlY3RlZCAoc2ljaykuDQoNCioqU3RlcCAyKio6IENob29zZSBhbiBhcHByb3ByaWF0ZSBDT1ZJRCB0ZXN0IGJhc2VkIG9uIHRoZSBxdWFsaXR5LiBGb3IgZXhhbXBsZSwgbG9va2luZyBmb3IgdGhlIHRlc3Qgd2l0aCBoaWdoIHNwZWNpZmljaXR5IGFuZCBzZW5zaXRpdml0eS4gTm90ZTogYFNwZWNpZmljaXR5ID0gUChUIC0gfCBObyBDT1ZJRClgIGFuZCBgU2Vuc2l0aXZpdHkgPSBQKFQgKyB8IENPVklEKWAuDQoNCioqU3RlcCAzKio6IFdhaXQgZm9yIHRoZSB0ZXN0IHJlc3VsdHMNCg0KKipTdGVwIDQqKjogQ29tcGFyaXNvbiBhbmQgZGVjaXNpb246IElmIHRoZSB0ZXN0IHJlc3VsdHMgZmFsbHMgaW4gY3JpdGljYWwgcmVnaW9uLCBSZWplY3QgSG8gJFxSaWdodGFycm93JCBkaWFnbm9zZSBDT1ZJRC4NCg0KDQoNCiMjIEFzc3VtcHRpb25zIGFuZCBTdGVwIGZvciBIeXBvdGhlc2lzIFRlc3RpbmcNCg0KRXZlcnkgcHJvY2VkdXJlIGZvciBzdGF0aXN0aWNhbCBpbmZlcmVuY2UgaW52b2x2ZXMgY2VydGFpbiBleHBsaWNpdCBhbmQgaW1wbGljaXQgYXNzdW1wdGlvbnMuIEEgZmFtaWx5IG9mIHJlbGF0ZWQgcHJvY2VkdXJlcyBzaGFyZXMgYSBjb3JlIHNldCBvZiBjb21tb24gYXNzdW1wdGlvbnMuIEFzIGEgbWFqb3IgZmFtaWx5LCBoeXBvdGhlc2lzIHRlc3RpbmcgZW5jb21wYXNzZXMgZGlmZmVyZW50IHRlc3QgdHlwZXMuIFRoZSBhc3N1bXB0aW9ucyBkaXNjdXNzZWQgbmV4dCBhcmUgY29tbW9uIHRvIG1hbnkgdGVzdHMgd2l0aGluIHRoaXMgZmFtaWx5LCBhc2lkZSBmcm9tIHRob3NlIHVuaXF1ZSB0byBhIHNwZWNpZmljIHRlc3QuDQoNCg0KIyMjIFNvbWUgQ29tbW9uIEFzc3VtcHRpb25zDQoNCiogKipEYXRhIFN0cnVjdHVyZSBBc3N1bXB0aW9ucyoqDQogICsgTW9zdCB0ZXN0cyByZXF1aXJlICoqSW5kZXBlbmRlbmNlIG9mIE9ic2VydmF0aW9ucyoqIGZvciBDcml0aWNhbCBmb3IgcHJvYmFiaWxpdHkgY2FsY3VsYXRpb25zIGFuZCBzdGFuZGFyZCBlcnJvciBlc3RpbWF0aW9uLg0KICArIEFsbCB0ZXN0cyByZXF1aXJlICoqUmFuZG9tIFNhbXBsaW5nKiogc28gdGhhdA0KICAgIC0gRGF0YSByZXByZXNlbnQgYSByYW5kb20gc2FtcGxlIGZyb20gdGhlIHBvcHVsYXRpb24NCiAgICAtIE5vIHN5c3RlbWF0aWMgc2VsZWN0aW9uIGJpYXMNCiAgICAtIEVuc3VyZXMgZ2VuZXJhbGl6YWJpbGl0eSBvZiByZXN1bHRzDQoNCiogKipNZWFzdXJlbWVudCAmIFNjYWxlIEFzc3VtcHRpb25zKioNCiAgKyAqKlJlbGlhYmxlIE1lYXN1cmVtZW50KiogbWVhbnMgdGhhdA0KICAgIC0gVmFyaWFibGVzIGFyZSBtZWFzdXJlZCB3aXRob3V0IHN5c3RlbWF0aWMgZXJyb3INCiAgICAtIE1lYXN1cmVtZW50IGluc3RydW1lbnRzIGFyZSB2YWxpZCBhbmQgcmVsaWFibGUNCiAgICAtIFJhbmRvbSBtZWFzdXJlbWVudCBlcnJvciBpcyBub3JtYWxseSBkaXN0cmlidXRlZA0KDQoqICoqU3RhdGlzdGljYWwgTW9kZWwgQXNzdW1wdGlvbnMqKg0KICArICAqKkRpc3RyaWJ1dGlvbmFsIEFzc3VtcHRpb25zKiogaW5jbHVkZQ0KICAgIC0gRm9yICoqUGFyYW1ldHJpYyBUZXN0cyoqLCBhIHNwZWNpZmljIGRpc3RyaWJ1dGlvbiBhc3N1bWVkIChlLmcuLCBub3JtYWxpdHkgZm9yIHQtdGVzdHMpLg0KICAgIC0gRm9yICoqbm9uLXBhcmFtZXRyaWMgdGVzdHMqKiwgZmV3ZXIgZGlzdHJpYnV0aW9uYWwgcmVxdWlyZW1lbnRzIGJ1dCBvZnRlbiBhc3N1bWU6IGNvbnRpbnVpdHksIHN5bW1ldHJ5LCBhbmQgaWRlbnRpY2FsIHNoYXBlIGFjcm9zcyBncm91cHMsIGV0Yy4NCiAgKyAqKkhvbW9nZW5laXR5IEFzc3VtcHRpb25zKioNCiAgICAtIEhvbW9nZW5laXR5IG9mIFZhcmlhbmNlIChIb21vc2NlZGFzdGljaXR5KSBpcyByZXF1aXJlZCBmb3IgdGVzdHMgcmVsYXRlZCB0byB0aGUgcmVncmVzc2lvbiBtb2RlbGluZy4NCiAgICAtIEhvbW9nZW5laXR5IG9mIENvdmFyaWFuY2UgaXMgY29tbW9ubHkgcmVxdWlyZWQgZm9yIG11bHRpdmFyaWF0ZSB0ZXN0cyBpbiB0aGUgbXVsdGl2YXJpYXRlIHJlZ3Jlc3Npb24gbW9kZWxpbmcuDQogIA0KKiAqKkluZmVyZW50aWFsIEFzc3VtcHRpb25zKioNCiAgKyBTYW1wbGUgU2l6ZSBSZXF1aXJlbWVudHMgcmVmbGVjdCB0aGUgYW1vdW50IG9mIGluZm9ybWF0aW9uIGluIHRoZSBkYXRhIHNldA0KICAgIC0gU3VmZmljaWVudCBTYW1wbGUgU2l6ZSBmb3IgYXBwbHlpbmcgQ2VudHJhbCBMaW1pdCBUaGVvcmVtIChDTFQpLCBwb3dlciBjYWxjdWxhdGlvbiwgZXRjLg0KICAgIC0gQWRlcXVhdGUgQ2VsbCBTaXplcyAoZm9yIGNhdGVnb3JpY2FsIHRlc3RzKSBmb3IgdmFsaWRpdHkgb2YgdGVzdHMuDQogICsgTGluZWFyaXR5IEFzc3VtcHRpb25zIGFyZSByZXF1aXJlZCBmb3IgcmVncmVzc2lvbiByZWxhdGVkIHRlc3RzLg0KICANCiAgDQogIA0KIyAgRm9ybWFsIEh5cG90aGVzaXMgVGVzdGluZw0KDQpUaGlzIHNlY3Rpb24gZm9jdXMgb24gc3lzdGVtYXRpYyBpbnRyb2R1Y3Rpb24gdG8gaHlwb3RoZXNpcyB0ZXN0aW5nOiBsb2dpY2FsIHN0ZXBzLCBmdW5kYW1lbnRhbCBjb21wb25lbnRzLCBwZXJmb3JtYW5jZSBhc3Nlc3NtZW50Lg0KDQojIyBMb2dpY2FsIFN0ZXBzDQoNCkh5cG90aGVzaXMgdGVzdGluZyBmb2xsb3dzIHRoZSBiYXNpYyBsb2dpY2FsIHByb2Nlc3Mgd2hpY2ggaXMgdXRpbGl6ZWQgaW4gc29mdHdhcmUgZGV2ZWxvcG1lbnQuIFdlIHdpbGwgdXNlIHNvbWUgZXhhbXBsZXMgZnJvbSBpbnRyb2R1Y3Rvcnkgc3RhdGlzdGljcyB0byBleHBsYWluIHRoZXNlIGJhc2ljIHN0ZXBzLiBBcyBhIGd1aWRlbGluZSwgSSBzdW1tYXJpemUgdGhlIHByb2Nlc3MgaW50byB0aGUgZm9sbG93aW5nIDYgc3RlcHM6DQoNCg0KKipTdGVwIDE6IEdhdGhlciBBdmFpbGFibGUgSW5mb3JtYXRpb24gZm9yIEh5cG90aGVzaXMgVGVzdGluZyoqOiBJbmZvcm1hdGlvbiBvbiBzYW1wbGUgc2l6ZSwgdGhlIHRlc3QgdHlwZSAocmlnaHQtdGFpbGVkLCBsZWZ0LXRhaWxlZCwgYW5kIHR3by10YWlsZWQpIGJhc2VkIG9uIHRoZSByZXNlYXJjaC9wcmFjdGljYWwgcXVlc3Rpb24sIHNpZ25pZmljYW5jZSBsZXZlbCwgZXRjLiANCg0KDQoqKlN0ZXAgMjogU3RhdGUgdGhlIEh5cG90aGVzZXMqKjogRm9ybWFsbHkgZGVmaW5lIHRoZSBjb21wZXRpbmcgY2xhaW1zLg0KDQoqICoqTnVsbCBIeXBvdGhlc2lzICgkSF8wJCkqKjogVGhlIGh5cG90aGVzaXMgb2YgIm5vIGVmZmVjdCwiICJubyBkaWZmZXJlbmNlLCIgb3IgInN0YXR1cyBxdW8uIiBJdCBpcyBhc3N1bWVkIHRydWUgdW50aWwgZXZpZGVuY2Ugc3VnZ2VzdHMgb3RoZXJ3aXNlLiBJdCBtdXN0IGNvbnRhaW4gYSBjb25kaXRpb24gb2YgZXF1YWxpdHkgKCQ9JCwgJFxsZXEkLCAkXGdlcSQpLiBUaGlzIG1lYW5zIHRoYXQgPGZvbnQgY29sb3IgPSAicmVkIj4qKnRoZSBjbGFpbWVkIHZhbHVlIGlzIGF0dGFpbmFibGUgdW5kZXIgdGhlIG51bGwgaHlwb3RoZXNpcyEqKjwvZm9udD4NCiAgKyBFeGFtcGxlOiAkSF8wOiBcbXUgPSBcbXVfMCQgKFRoZSBwb3B1bGF0aW9uIG1lYW4gJFxtdSQgZXF1YWxzIGEgc3BlY2lmaWMgdmFsdWUgJFxtdV8wJCkNCg0KKiAqKkFsdGVybmF0aXZlIEh5cG90aGVzaXMgKCRIXzEkIG9yICRIX2EkKSoqOiBUaGUgaHlwb3RoZXNpcyB5b3UgaG9wZSB0byBzdXBwb3J0LiBJdCBjb250cmFkaWN0cyAkSF8wJCBhbmQgcmVwcmVzZW50cyBhICJuZXcgZWZmZWN0IiBvciAiZGlmZmVyZW5jZS4iIEl0IGlzIGRlZmluZWQgYnkgdGhlIHJlc2VhcmNoIHF1ZXN0aW9uICgkPCQsICQ+JCwgb3IgJFxuZXEkKS4NCiAgKyBFeGFtcGxlczoNCiAgICAtICRIXzE6IFxtdSA+IFxtdV8wJCAoUmlnaHQtdGFpbGVkIHRlc3QpDQogICAgLSAkSF8xOiBcbXUgPCBcbXVfMCQgKExlZnQtdGFpbGVkIHRlc3QpDQogICAgLSAkSF8xOiBcbXUgXG5lcSBcbXVfMCQgKFR3by10YWlsZWQgdGVzdCkNCg0KKipTdGVwIDM6IFNlbGVjdCBBbiBBcHByb3ByaWF0ZSBUZXN0cyBCYXNlZCBvbiBHaXZlbiBJbmZvcm1hdGlvbiBhbmQgRXZhbHVhdGUgdGhlIFRlc3QgU3RhdGlzdGljKioNCiAgDQoqIFRoaXMgaXMgYSBzdGFuZGFyZGl6ZWQgdmFsdWUgdGhhdCBtZWFzdXJlcyB0aGUgZGlzdGFuY2UgYmV0d2VlbiB0aGUgc2FtcGxlIHN0YXRpc3RpYyBhbmQgdGhlIGh5cG90aGVzaXplZCBwYXJhbWV0ZXIgdW5kZXIgJEhfMCQuIEZvciBleGFtcGxlLCBpbiBpbnRyb2R1Y3Rvcnkgc3RhdGlzdGljcw0KICArIE9uZS1zYW1wbGUgei10ZXN0OiANCiQkDQogIHogPSBcZnJhY3tcYmFye3h9IC0gXG11XzB9e1xzaWdtYS9cc3FydHtufX0NCiQkDQogICsgT25lLXNhbXBsZSB0LXRlc3Q6IA0KJCQNCnQgPSBcZnJhY3tcYmFye3h9IC0gXG11XzB9e3MvXHNxcnR7bn19DQokJA0KICArIENoaS1zcXVhcmUgdGVzdDogDQokJA0KXGNoaV4yID0gXHN1bSBcZnJhY3soT19pIC0gRV9pKV4yfXtFX2l9DQokJA0KICANCg0KKipTdGVwIDQ6IERldGVybWluZSB0aGUgQ3JpdGljYWwgVmFsdWUocykgYW5kL29yIFAtdmFsdWUqKjogVHdvIG1haW4gYXBwcm9hY2hlcyAodGhleSBhcmUgY29uY2VwdHVhbGx5IGxpbmtlZCkgYW5kIGJvdGggYXBwcm9hY2hlcyByZXF1aXJlcyB0aGUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHR5cGUgb2YgdGhlIHRlc3QgYXMgaWxsdXN0cmF0ZWQgaW4gdGhlICoqYWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyoqLg0KICANCiogKipDcml0aWNhbCBWYWx1ZSBBcHByb2FjaCoqOiBGaW5kIHRoZSB0aHJlc2hvbGQgdmFsdWUocykgZnJvbSB0aGUgc3RhdGlzdGljYWwgZGlzdHJpYnV0aW9uIChlLmcuLCAkel97XGFscGhhfSQsICR0X3tcYWxwaGEsIGRmfSQpIHRoYXQgY29ycmVzcG9uZCB0byB0aGUgc2lnbmlmaWNhbmNlIGxldmVsICRcYWxwaGEkIGFuZCB0aGUgdGVzdCB0eXBlIChyaWdodC10YWlsZWQsIGxlZnQtdGFpbGVkLCBvciB0ZW8tdGFpbGVkIHRlc3QpLiAgDQoNCg0KKiAqKlAtdmFsdWUgQXBwcm9hY2gqKjogQ2FsY3VsYXRlIHRoZSBwLXZhbHVl4oCUdGhlIHByb2JhYmlsaXR5IG9mIG9idGFpbmluZyBhIHRlc3Qgc3RhdGlzdGljIGF0IGxlYXN0IGFzIGV4dHJlbWUgYXMgdGhlIG9uZSBvYnNlcnZlZCwgYXNzdW1pbmcgJEhfMCQgaXMgdHJ1ZS4gDQoNCg0KKipTdGVwIDU6IE1ha2UgYSBEZWNpc2lvbioqOiBDb21wYXJlIHlvdXIgcmVzdWx0IGZyb20gU3RlcCAzIHRvIHRoZSB0ZXN0IHN0YXRpc3RpYyBvciB0aGUgZ2l2ZW4gc2lnbmlmaWNhbnQgbGV2ZWwuIDxmb250IGNvbG9yID0gInJlZCI+KipDcnVjaWFsIE5vdGUqKjogWW91IG5ldmVyICJhY2NlcHQiICRIXzAkLiBZb3UgZWl0aGVyIHJlamVjdCBpdCBvciBmYWlsIHRvIHJlamVjdCBpdC4gRmFpbGluZyB0byByZWplY3QgbWVhbnMgdGhlcmUgaXMgaW5zdWZmaWNpZW50IGV2aWRlbmNlIGFnYWluc3QgJEhfMCQsIG5vdCBwcm9vZiB0aGF0IGl0IGlzIHRydWUuPC9mb250Pg0KDQoqICoqVXNpbmcgQ3JpdGljYWwgVmFsdWVzKio6IElmIHx0ZXN0IHN0YXRpc3RpY3wgPiB8Y3JpdGljYWwgdmFsdWV8ICRcUmlnaHRhcnJvdyQgUmVqZWN0ICRIXzAkOyBvdGhlcndpc2UsIENvbmNsdWRlICRIXzAkLg0KDQoqICoqVXNpbmcgUC12YWx1ZSoqOiAgSWYgcC12YWx1ZSAkXGxlIFxhbHBoYSQgJFxSaWdodGFycm93JCBSZWplY3QgJEhfMCQ7IElmIHAtdmFsdWUgJD4gXGFscGhhJCAkXFJpZ2h0YXJyb3ckIEZhaWwgdG8gUmVqZWN0ICRIXzAkLg0KDQoNCioqU3RlcCA2OiBTdGF0ZSB0aGUgQ29uY2x1c2lvbiBpbiBDb250ZXh0Kio6IFRyYW5zbGF0ZSB0aGUgc3RhdGlzdGljYWwgZGVjaXNpb24gaW50byBhIGNsZWFyLCBwbGFpbi1sYW5ndWFnZSBzdGF0ZW1lbnQgYWJvdXQgdGhlIHJlc2VhcmNoIHF1ZXN0aW9uLg0KDQoqICoqSWYgeW91IHJlamVjdCAkSF8wJCoqOiAgVGhlcmUgaXMgc3VmZmljaWVudCBzdGF0aXN0aWNhbCBldmlkZW5jZSBhdCB0aGUgJFxhbHBoYSQgbGV2ZWwgdG8gY29uY2x1ZGUgdGhhdCBbc3RhdGUgJEhfMSQgaW4gY29udGV4dF0uICoqRm9yIGV4YW1wbGUqKiwgIDxmb250IGNvbG9yID0gInJlZCI+VGhlcmUgaXMgc3VmZmljaWVudCBldmlkZW5jZSAoJFxhbHBoYT0wLjA1JCkgdG8gY29uY2x1ZGUgdGhhdCB0aGUgbmV3IGRydWcgbG93ZXJzIGJsb29kIHByZXNzdXJlIG1vcmUgdGhhbiB0aGUgcGxhY2Viby4iPC9mb250Pg0KDQoqICoqSWYgeW91IGZhaWwgdG8gcmVqZWN0ICRIXzAkKio6ICJUaGVyZSBpcyBpbnN1ZmZpY2llbnQgc3RhdGlzdGljYWwgZXZpZGVuY2UgYXQgdGhlICRcYWxwaGEkIGxldmVsIHRvIGNvbmNsdWRlIHRoYXQgW3N0YXRlICRIXzEkIGluIGNvbnRleHRdLiIgKipGb3IgZXhhbXBsZSoqOiA8Zm9udCBjb2xvciA9ICJyZWQiPlRoZXJlIGlzIGluc3VmZmljaWVudCBldmlkZW5jZSAoJFxhbHBoYT0wLjA1JCkgdG8gY29uY2x1ZGUgdGhhdCB0aGUgbmV3IG1hbnVmYWN0dXJpbmcgcHJvY2VzcyBjaGFuZ2VzIHRoZSBwcm9kdWN0J3Mgc3RyZW5ndGguIjwvZm9udD4NCg0KXA0KDQojIyBTYW1wbGluZyBEaXN0cmlidXRpb24gb2YgVGVzdCBTdGF0aXN0aWMNCg0KT25lIG9mIHRoZSBjcml0aWNhbCBzdGVwcyBpbiB0aGUgbG9naWNhbCBwcm9jZXNzIGFib3ZlIGlzIHRvIGZpbmQgdGhlIGNyaXRpY2FsIHZhbHVlIG9yIHAtdmFsdWUgdG8gbWFrZSBhIGRlY2lzaW9uLiBCb3RoIGFyZSBkZXBlbmRlbnQgb24gdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgdGVzdCBzdGF0aXN0aWMsIG1vcmUgc3BlY2lmaWNhbGx5LCB0aGUgKipzYW1wbGluZyBkaXN0cmlidXRpb24qKiBvZiB0aGUgdGVzdCBzdGF0aXN0aWMuIEluIGZhY3QsIGEgKip0ZXN0IHN0YXRpc3RpYyoqIGlzIGVzc2VudGlhbGx5IGEgKipwaXZvdGFsIHF1YW50aXR5Kiogd2hvc2UgZGlzdHJpYnV0aW9uIGlzICoqaW5kZXBlbmRlbnQqKiBvZiB0aGUgcGFyYW1ldGVycy4gV2UgY2FuIHNlZSB0aGlzIHBhdHRlcm4gaW4gdGhlIGV4YW1wbGVzIGluIFN0ZXAgMyBvZiB0aGUgbG9naWNhbCBwcm9jZXNzIGZvciBoeXBvdGhlc2lzIHRlc3RpbmcuDQoNCioqRXhhY3QgUGl2b3RhbCBRdWFudGl0eSoqIC0gV2hpbGUgKipleGFjdCBwaXZvdGFsIHF1YW50aXR5KiogaXMgbm90IGEgZm9ybWFsIHRleHRib29rIHRlcm0sIGl0IGVtcGhhc2l6ZXMgdGhlIHByb3BlcnR5IHRoYXQgYSBmdW5jdGlvbiBvZiB0aGUgc2FtcGxlIGFuZCB0aGUgdHJ1ZSBwYXJhbWV0ZXIgaGFzIGEgKipmdWxseSBzcGVjaWZpZWQqKiwgKipleGFjdCBzYW1wbGluZyBkaXN0cmlidXRpb24qKiAoc3RhbmRhcmQgbm9ybWFsLCB0LCBjaGnigJFzcXVhcmUsIGV0Yy4pLCB3aGljaCBpcyBwaXZvdGFsIGZvciBleGFjdCBpbmZlcmVuY2UuDQoNCioqQXN5bXB0b3RpYyBwaXZvdGFsIHF1YW50aXR5KiogLSBUaGUgbmFtZSBpdHNlbGYgY29udmV5cyB0aGUga2V5IHByb3BlcnR5OiBpdCBpcyBhIHF1YW50aXR5IChhIGZ1bmN0aW9uIG9mIHRoZSBkYXRhIGFuZCB0aGUgcGFyYW1ldGVyKSB3aG9zZSBkaXN0cmlidXRpb24gKipjb252ZXJnZXMqKiB0byBhIGZpeGVkLCBrbm93biBmb3JtIChzdWNoIGFzIHN0YW5kYXJkIG5vcm1hbCkgKiphcyB0aGUgc2FtcGxlIHNpemUgZ3Jvd3MgdG8gaW5maW5pdHkqKi4gVGhpcyBtZWFucywgdGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBpcyBvbmx5IGFuIGFwcHJveGltYXRpb24uIE1vc3QgbGlrZWxpaG9vZCBiYXNlZCBoeXBvdGhlc2lzIHRlc3RzIGV2ZW50dWFsbHkgZGVmaW5lIGFuIGFzeW1wdG90aWMgcGl2b3RhbCBxdWFudGl0eSB0byBhcHByb3hpbWF0ZSBhIGZpeGVkIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBpbmRlcGVuZGVudCBvbiBwYXJhbWV0ZXJzIGFuZCBzYW1wbGUgZGF0YS4NCg0KV2Ugd2lsbCBkaXNjdXNzIGFzeW1wdG90aWMgaHlwb3RoZXNpcyB0ZXN0aW5nIGJhc2VkIG9uIHRoZSBsaWtlbGlob29kIGluIHRoZSBuZXh0IG1vZHVsZS4NCg0KDQojIyBQLXZhbHVlIGFuZCBQLUhhY2tpbmcNCg0KVGhlIG1hdGhlbWF0aWNhbCBkZWZpbml0aW9uIG9mIHRoZSBw4oCRdmFsdWUgaW52b2x2ZXMgY29uZGl0aW9uYWwgcHJvYmFiaWxpdHkgYW5kIGlzIG5vdCBlYXN5IHRvIGdyYXNwLiBBbiBpbmZvcm1hbCBkZWZpbml0aW9uLCBnaXZlbiBpbiBhbiBBbWVyaWNhbiBTdGF0aXN0aWNhbCBBc3NvY2lhdGlvbiAoQVNBKSBzdGF0ZW1lbnQsIHJlYWRzOg0KDQo+IOKAnEluZm9ybWFsbHksIGEgcOKAkXZhbHVlIGlzIHRoZSBwcm9iYWJpbGl0eSwgdW5kZXIgYSBzcGVjaWZpZWQgc3RhdGlzdGljYWwgbW9kZWwsIHRoYXQgYSBzdGF0aXN0aWNhbCBzdW1tYXJ5IG9mIHRoZSBkYXRhIHdvdWxkIGJlIGVxdWFsIHRvIG9yIG1vcmUgZXh0cmVtZSB0aGFuIGl0cyBvYnNlcnZlZCB2YWx1ZS7igJ0NCg0KDQoNCg0KIyMgR29vZG5lc3MgKEJhZG5lc3MpIG9mIFRlc3RzDQoNClRoaXMgaXMgYSBmdW5kYW1lbnRhbCBjb25jZXB0IGluIHN0YXRpc3RpY3MuIEhlcmXigJlzIGEgY2xlYXIgYnJlYWtkb3duIG9mIHBlcmZvcm1hbmNlIG1lYXN1cmVzIGFuZCBlcnJvciB0eXBlcyBpbiBoeXBvdGhlc2lzIHRlc3RpbmcsIGZyYW1lZCBhcm91bmQgdGhlIGNsYXNzaWMgKipjb25mdXNpb24gbWF0cml4KiogZm9yIGEgYmluYXJ5IHRlc3QgKEhvIHZzLiBIYSkuIE1vc3Qgb2YgdGhlIHBlcmZvcm1hbmNlIG1lYXN1cmVzIGFyZSBkZWZpbmVkIGJhc2VkIG9uIHRoZSBmb2xsb3dpbmcgY29uZnVzaW9uIG1hdHJpeC4NCg0KDQoqKkEuIERlY2lzaW9uIChDb25mdXNpb24pIE1hdHJpeCoqDQoNCg0KYGBge3IgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNjAlIn0NCmluY2x1ZGVfZ3JhcGhpY3MoImNvbmZ1c2lvbi1tYXRyaXgucG5nIikNCmBgYA0KDQoqKkNvbW1lbnRzKio6IFNldmVyYWwgcHJhY3RpY2FsbHkgaW1wb3J0YW50IGZhY3RzIGFib3V0IHRoZSAqKmNvbmZ1c2lvbiBtYXRyaXggZm9yIGh5cG90aGVzaXMgdGVzdGluZyoqOg0KDQoqIFRoZSBjb25kaXRpb25hbCBwcm9iYWJpbGl0aWVzICRcYWxwaGEkIGFuZCAkXGJldGEkIChzZWUgdGhlIG1hdGhlbWF0aWNhbCBkZWZpbml0aW9ucyBiZWxvdykgYXJlICoqbm90IGVzdGltYWJsZSoqIGJhc2VkIG9uIGEgc2luZ2xlIGRhdGEgc2V0IHNpbmNlIHdlIGRvbid0IGtub3cgKipUUlVFKiogc3RhdHVzIG9mIG51bGwgYW5kIGFsdGVybmF0aXZlIGh5cG90aGVzZXMuIEluIG90aGVyIHdvcmRzLCB0aGUgKipjb25mdXNpb24gbWF0cml4IGZvciBoeXBvdGhlc2lzIHRlc3RpbmcqKiByZXByZXNlbnRzICoqcG90ZW50aWFsKiogb3V0Y29tZXMgdW5kZXIgZGlmZmVyZW50IHN0YXRlcyBvZiBuYXR1cmUsICoqbm90IGFjdHVhbCBvYnNlcnZlZCBwcm9wb3J0aW9ucyoqLg0KDQoqIFNpbWlsYXIgdG8gdGhlIGludGVycHJldGF0aW9uIG9mIGEgJDEwMCgxLVxhbHBoYSlcJSQgY29uZmlkZW5jZSBpbnRlcnZhbDogaWYgd2Ugd2VyZSB0byB0YWtlIDEwMCByYW5kb20gc2FtcGxlcyBvZiB0aGUgc2FtZSBzaXplIHVzaW5nIHRoZSBzYW1lIHNhbXBsaW5nIHByb3RvY29sLCBhbmQgY29uc3RydWN0IDEwMCBjb25maWRlbmNlIGludGVydmFscyBhdCB0aGF0IGxldmVsLCB3ZSB3b3VsZCBleHBlY3QgYWJvdXQgJDEwMCgxLVxhbHBoYSkkIG9mIHRob3NlIGludGVydmFscyB0byBjb250YWluIHRoZSB0cnVlIHBhcmFtZXRlciB2YWx1ZS4gVGhlIGNvbmZ1c2lvbiBtYXRyaXggaW4gaHlwb3RoZXNpcyB0ZXN0aW5nIGFsc28gZGVzY3JpYmVzICoqbG9uZ+KAkXJ1biBoeXBvdGhldGljYWwgb3V0Y29tZXMqKi4gSXQgaWxsdXN0cmF0ZXM6DQogICsgV2hhdCAqKndvdWxkIGhhcHBlbioqIGlmIHdlIHJlcGVhdGVkIHRoZSBzYW1lIGV4cGVyaW1lbnQgbWFueSB0aW1lcywNCiAgKyAqKkNvbmRpdGlvbmFsIG9uKiogZWl0aGVyIEhvIGFsd2F5cyBiZWluZyB0cnVlICh0aGUgbGVmdCBjb2x1bW4pIG9yIEhhIGFsd2F5cyBiZWluZyB0cnVlICh0aGUgcmlnaHQgY29sdW1uKS4NCg0KKiBUaGUgcGFyYWxsZWwgZnJlcXVlbnRpc3QgaW50ZXJwcmV0YXRpb25zIGF0ICRcYWxwaGEgPSAwLjA1JA0KICArICoqQ29uZmlkZW5jZSBJbnRlcnZhbCoqOiBJZiB3ZSBjb25zdHJ1Y3RlZCAxMDAgY29uZmlkZW5jZSBpbnRlcnZhbHMgZnJvbSAxMDAgaW5kZXBlbmRlbnQgc2FtcGxlcywgd2UnZCBleHBlY3QgYWJvdXQgOTUgdG8gY29udGFpbiB0aGUgdHJ1ZSBwYXJhbWV0ZXIgdmFsdWUuDQogICsgKipIeXBvdGhlc2lzIFRlc3RpbmcgKENvbmZ1c2lvbiBNYXRyaXgpKio6IDxmb250IGNvbG9yID0gImRhcmtyZWQiPihJKSBJZiB3ZSBwZXJmb3JtZWQgMTAwIGh5cG90aGVzaXMgdGVzdHMgd2hlbiBIbyBpcyB0cnVlLCB3ZSdkIGV4cGVjdCBhYm91dCA1IFR5cGUgSSBlcnJvcnMgW2ZhbHNlIHBvc2l0aXZlc108L2ZvbnQ+IEFORCA8Zm9udCBjb2xvciA9ICJibHVlIj4oSUkpIElmIHdlIHBlcmZvcm1lZCAxMDAgaHlwb3RoZXNpcyB0ZXN0cyB3aGVuIEhhIGlzIHRydWUgd2l0aCBlZmZlY3Qgc2l6ZSAkXGRlbHRhJCwgd2UnZCBleHBlY3QgYWJvdXQgJCgxLVxhbHBoYSnDlzEwMCQgY29ycmVjdCByZWplY3Rpb25zIFt0cnVlIHBvc2l0aXZlc10uPC9mb250Pg0KDQoqICoqcC12YWx1ZSwgc2lnbmlmaWNhbnQgbGV2ZWwsIGFuZCB0eXBlIEkgZXJyb3IgcmF0ZSoqOiBUaGVzZSB0aHJlZSBjb25jZXB0cyBmb3JtIHRoZSBjb3JlIGRlY2lzaW9uLW1ha2luZyBmcmFtZXdvcmsgb2YgZnJlcXVlbnRpc3Qgc3RhdGlzdGljcy4gDQogICsgKipTaWduaWZpY2FuY2UgTGV2ZWwgKCRcYWxwaGEkKSoqIGlzIGEgdGhyZXNob2xkIChkZXNpZ24gcGFyYW1ldGVyKSBmb3IgZGVjaXNpb24tbWFraW5nIGFuZCBkZXRlcm1pbmVkICoqYmVmb3JlKiogZGF0YSBjb2xsZWN0aW9uLg0KICArICoqcC12YWx1ZSoqIGlzIGEgZGF0YS1kZXBlbmRlbnQgbWVhc3VyZSBvZiBldmlkZW5jZSBzdHJlbmd0aCBjYWxjdWxhdGVkIGZyb20gZGF0YSAqKmFmdGVyKiogZGF0YSBjb2xsZWN0aW9uLgkNCiAgKyAqKlR5cGUgSSBFcnJvciBQcm9iYWJpbGl0eSoqIGlzIHRoZSByaXNrIG9mIGZhbHNlIHBvc2l0aXZlIGJhc2VkIG9uIExvbmctcnVuIGZyZXF1ZW5jeS4gSXQgaXMgZGV0ZXJtaW5lZCBjb25jZXB0dWFsbHkgYmVmb3JlIG9yIGFmdGVyIGRhdGEgY29sbGVjdGlvbi4JDQoNCg0KDQoqKkIuIE1hdGhlbWF0aWNhbCBEZWZpbml0aW9ucyoqDQoNCk1vc3Qgb2YgdGhlIHRlc3QgcGVyZm9ybWFuY2UgYXJlIGRlZmluZWQgaW4gdGhlIGZvcm0gb2YgY29uZGl0aW9uYWwgcHJvYmFiaWxpdGllcy4gVGhleSBjYW4gYmUgZXN0aW1hdGVkIGJhc2VkIG9uIHRoZSBvYnNlcnZlZCAqKmNvbmZ1c2lvbiBtYXRyaXgqKiBkZWZpbmVkIGFib3ZlLiANCg0KDQoqICoqVHlwZSBJIEVycm9yICgkXGFscGhhJCkqKjogDQoNCiQkDQpcYWxwaGEgPSBQKFx0ZXh0e1JlamVjdCB9IEhfMCBcbWlkIEhfMCBcdGV4dHsgdHJ1ZX0pIA0KJCQNCg0KDQoNCiogKipUeXBlIElJIEVycm9yICgkXGJldGEkKSoqOg0KDQokJA0KXGJldGEgPSBQKFx0ZXh0e0ZhaWwgdG8gcmVqZWN0IH0gSF8wIFxtaWQgSF8xIFx0ZXh0eyB0cnVlfSkgDQokJA0KDQoqICoqUG93ZXIgKCQxLVxiZXRhJCkqKjoNCg0KJCQNClx0ZXh0e1Bvd2VyfSA9IFAoXHRleHR7UmVqZWN0IH0gSF8wIFxtaWQgSF8xIFx0ZXh0eyB0cnVlfSkgPSAxIC0gXGJldGENCiQkDQoNClRoZSBtZWFzdXJlcyBhYm92ZSBhc3Nlc3MgcGVyZm9ybWFuY2UgKipsb2NhbGx5KiosIG1lYW5pbmcgdGhhdCB0aGUgcG93ZXIgcmVmbGVjdHMgdGhlIHNwZWNpZmljIHZhbHVlIGNsYWltZWQgaW4gdGhlIGh5cG90aGVzaXMuIEdlbmVyYWxseSwgd2UgdXNlIHBvd2VyIHRvIGNvbXBhcmUgdGhlIHBlcmZvcm1hbmNlIChnb29kbmVzcyBvciBiYWRuZXNzKSBvZiB0d28gb3IgbW9yZSB0ZXN0cy4NCg0KSWYgd2UgZnJlZSB0aGUgY2xhaW1lZCB2YWx1ZSBpbiB0aGUgaHlwb3RoZXNpcywgd2UgdGhlbiB0dXJuIHRoZSBsb2NhbCBwZXJmb3JtYW5jZSBtZWFzdXJlcyBpbnRvIGdsb2JhbCBtZWFzdXJlcy4gRm9yIGV4YW1wbGUsIHdlIGNhbiBkZWZpbmUgdGhlIHBvd2VyIGZ1bmN0aW9uIGFzIGZvbGxvd3M6DQoNCiogKipQb3dlciBGdW5jdGlvbioqOiBBc3N1bWUgdGhlIGNsYWltZWQgdmFsdWUgaW4gdGhlIGh5cG90aGVzaXMgaXMgYW4gdW5rbm93biBwYXJhbWV0ZXIgJFx0aGV0YSQuIFRoaXMgbWVhbnMgdGhlIHBvd2VyIG9mIHRoZSB0ZXN0IGRlcGVuZHMgb24gdGhlIGNob2ljZSBvZiAkXHRoZXRhJC4gVGhlcmVmb3JlLCB3ZSBjYW4gZGVmaW5lIHRoZSBwb3dlciBmdW5jdGlvbiBhczoNCg0KJCQNClxwaShcdGhldGEpID0gUChcdGV4dHtSZWplY3QgfSBIXzAgXG1pZCBcdGhldGEpIA0KJCQNCg0KIyBIb3cgSHlwb3RoZXNpcyBUZXN0aW5nIGlzIEFwcGxpZWQgaW4gQ2xpbmljYWwgVHJpYWxzDQoNCioqSHlwb3RoZXNpcyB0ZXN0aW5nKiogaXMgbm90IGp1c3QgdXNlZCBpbiBjbGluaWNhbCB0cmlhbHPigJRpdCBpcyB0aGUgbWFuZGF0b3J5LCBmb3JtYWwgc3RhdGlzdGljYWwgbWV0aG9kb2xvZ3kgdGhhdCB1bmRlcnBpbnMgdGhlIGVudGlyZSBGREEgZHJ1ZyBhcHByb3ZhbCBwcm9jZXNzLiBJdCBwcm92aWRlcyBhbiBvYmplY3RpdmUsIHF1YW50aXRhdGl2ZSBzdGFuZGFyZCBmb3IgZGVjaWRpbmcgd2hldGhlciB0aGUgZXZpZGVuY2Ugb2YgYSBkcnVn4oCZcyBlZmZpY2FjeSBpcyBzdHJvbmcgZW5vdWdoIHRvIHdhcnJhbnQgbWFraW5nIGl0IGF2YWlsYWJsZSB0byBwYXRpZW50cywgYWxsIHdoaWxlIGNvbnRyb2xsaW5nIHRoZSByaXNrIG9mIGZhbHNlIGNsYWltcy4gVGhlIHByb2Nlc3MgaXMgYSBzZXF1ZW50aWFsIGFwcGxpY2F0aW9uIG9mIGh5cG90aGVzaXMgdGVzdHMsIHdpdGggZWFjaCBwaGFzZSBhZGRyZXNzaW5nIG1vcmUgZGVmaW5pdGl2ZSBxdWVzdGlvbnMgdW5kZXIgaW5jcmVhc2luZ2x5IHN0cmluZ2VudCBzdGF0aXN0aWNhbCBjb250cm9scy4NCg0KVGhpcyBzZWN0aW9uIG91dGxpbmVzIHRoZSBrZXkgc3RhZ2VzIG9mIGNvbmZpcm1hdG9yeSBjbGluaWNhbCB0cmlhbHMsIGhpZ2hsaWdodGluZyB0aGUgdXNlIG9mIGh5cG90aGVzaXMgdGVzdGluZyBpbiBlYWNoIHBoYXNlLg0KDQojIyBTdGFnZXMgb2YgQ2xpbmljYWwgVHJpYWxzDQoNCkNsaW5pY2FsIHRyaWFscyBhcmUgY29uZHVjdGVkIGluIGEgc2VyaWVzIG9mIHBoYXNlZCBzdGVwcywgZWFjaCBkZXNpZ25lZCB0byBhbnN3ZXIgc3BlY2lmaWMgcXVlc3Rpb25zIGFib3V0IGEgbmV3IG1lZGljYWwgaW50ZXJ2ZW50aW9uJ3Mgc2FmZXR5LCBlZmZpY2FjeSwgYW5kIGFwcHJvcHJpYXRlIHVzZS4gSGVyZSBpcyBhIHN0YW5kYXJkIG91dGxpbmUgb2YgdGhlIHN0YWdlcy4NCg0KDQoqKkFkZGl0aW9uYWwgS2V5IFN0YWdlIChQcmUtVHJpYWwpKioNCg0KKiAqKlByZWNsaW5pY2FsIFJlc2VhcmNoKio6IEJlZm9yZSBodW1hbiB0ZXN0aW5nIGJlZ2lucywgbGFib3JhdG9yeSAoaW4gdml0cm8gLSBvdXRzaWRlIGxpdmluZyBvcmdhbmlzbSkgYW5kIGFuaW1hbCAoaW4gdml2byAtIGluIGxpdmluZyBvcmdhbmlzbSkgc3R1ZGllcyBhcmUgY29uZHVjdGVkIHRvIGdhdGhlciBwcmVsaW1pbmFyeSBlZmZpY2FjeSwgdG94aWNpdHksIGFuZCBwaGFybWFjb2tpbmV0aWMgaW5mb3JtYXRpb24uIFRoaXMgaXMgbm90IGNvbnNpZGVyZWQgYSAiY2xpbmljYWwiIHBoYXNlLCBhcyBpdCBkb2VzIG5vdCBpbnZvbHZlIGh1bWFuIHBhcnRpY2lwYW50cy4NCg0KVGhlIHNwb25zb3Igc3VibWl0cyBhbiAqKkludmVzdGlnYXRpb25hbCBOZXcgRHJ1ZyAoSU5EKSoqIGFwcGxpY2F0aW9uIHdpdGggKipwcmUtY2xpbmljYWwqKiBkYXRhLCBtYW51ZmFjdHVyaW5nIGluZm8sIGFuZCB0aGUgUGhhc2UgMSBzdHVkeSBwbGFuLCByZXF1aXJpbmcgRkRBIGFwcHJvdmFsIHRvIHN0YXJ0IGh1bWFuIHRyaWFscy4NCg0KXA0KDQoqKlBoYXNlIDE6IFNhZmV0eSAmIERvc2FnZSoqIC0gYW4gaW5pdGlhbCBleHBsb3JhdG9yeSBzdGFnZS4gRGF0YSBvbiBzYWZldHkgYW5kIGRvc2FnZSBpcyBzdWJtaXR0ZWQsIGFuZCB0aGUgRkRBIG11c3QgcGVybWl0IHRoZSB0cmlhbCB0byBhZHZhbmNlIHRvIFBoYXNlIDIgaWYgcmVzdWx0cyBhcmUgZmF2b3JhYmxlLg0KDQoqICoqUHJpbWFyeSBHb2FsKio6IEFzc2VzcyB0aGUgc2FmZXR5LCB0b2xlcmFiaWxpdHksIGFuZCBwaGFybWFjb2tpbmV0aWNzIChob3cgdGhlIGJvZHkgcHJvY2Vzc2VzIHRoZSBkcnVnKSBpbiBhIHNtYWxsIGdyb3VwICgyMC0xMDApLg0KDQoqICoqUGFydGljaXBhbnRzKio6IFVzdWFsbHkgaGVhbHRoeSB2b2x1bnRlZXJzLCB0aG91Z2ggZm9yIHNlcmlvdXMgY29uZGl0aW9ucyAoZS5nLiwgY2FuY2VyKSwgcGFydGljaXBhbnRzIG1heSBiZSBwYXRpZW50cy4NCg0KKiAqKktleSBGb2N1cyoqOiBEZXRlcm1pbmUgYSBzYWZlIGRvc2FnZSByYW5nZSBhbmQgaWRlbnRpZnkgY29tbW9uIHNpZGUgZWZmZWN0cy4NCg0KDQoqKlBoYXNlIDI6IEVmZmljYWN5ICYgU2lkZSBFZmZlY3RzKiogLSBhbiBleHBsb3JhdG9yeSBzdGFnZS4gRWZmaWNhY3kgYW5kIHNpZGUgZWZmZWN0cyBhcmUgYXNzZXNzZWQ7IHBvc2l0aXZlIGZpbmRpbmdzIGFsbG93IHByb2dyZXNzaW9uIHRvIFBoYXNlIDMuDQoNCiogKipQcmltYXJ5IEdvYWwqKjogRXZhbHVhdGUgdGhlIGludGVydmVudGlvbidzIHByZWxpbWluYXJ5IGVmZmljYWN5IGFuZCBmdXJ0aGVyIGFzc2VzcyBpdHMgc2FmZXR5Lg0KDQoqICoqUGFydGljaXBhbnRzKio6IEEgbGFyZ2VyIGdyb3VwICh1cCB0byBzZXZlcmFsIGh1bmRyZWQpIG9mIHBhdGllbnRzIHdpdGggdGhlIHRhcmdldCBkaXNlYXNlIG9yIGNvbmRpdGlvbi4NCg0KKiAqKktleSBGb2N1cyoqOiBHYXRoZXIgZGF0YSBvbiB3aGV0aGVyIHRoZSBkcnVnIHdvcmtzIChlLmcuLCBzaHJpbmtzIHR1bW9ycywgbG93ZXJzIGJsb29kIHByZXNzdXJlKSBhbmQgbW9uaXRvciBzaG9ydC10ZXJtIHNpZGUgZWZmZWN0cy4gVGhpcyBwaGFzZSBvZnRlbiBleHBsb3JlcyBkaWZmZXJlbnQgZG9zaW5nIHJlZ2ltZW5zLg0KDQoNCioqUGhhc2UgMzogQ29uZmlybWF0b3J5ICYgTW9uaXRvcmluZyoqIC0gYSBjb25maXJtYXRvcnkgc3RhZ2UuIEFmdGVyIGxhcmdlLXNjYWxlIHRyaWFscyBjb25maXJtIGVmZmVjdGl2ZW5lc3MgYW5kIHNhZmV0eSwgdGhlIHNwb25zb3Igc3VibWl0cyBhICoqTmV3IERydWcgQXBwbGljYXRpb24gKE5EQSkqKiBmb3IgRkRBIHJldmlldyBhbmQgYXBwcm92YWwgdG8gbWFya2V0IHRoZSBkcnVnLg0KDQoqICoqUHJpbWFyeSBHb2FsKio6IENvbmZpcm0gZWZmZWN0aXZlbmVzcywgbW9uaXRvciBsb25nLXRlcm0gc2lkZSBlZmZlY3RzLCBhbmQgY29tcGFyZSB0aGUgbmV3IGludGVydmVudGlvbiB0byB0aGUgY3VycmVudCBzdGFuZGFyZCB0cmVhdG1lbnQuDQoNCiogKipQYXJ0aWNpcGFudHMqKjogTGFyZ2UgZ3JvdXBzICgzMDAgdG8gMywwMDArIHBhdGllbnRzKSBhY3Jvc3MgbXVsdGlwbGUgcmVzZWFyY2ggY2VudGVycy4NCg0KKiAqKktleSBGb2N1cyoqOiBQcm92aWRlIHRoZSBkZWZpbml0aXZlIGV2aWRlbmNlIG9mIGJlbmVmaXQgYW5kIHJpc2sgcmVxdWlyZWQgZm9yIHJlZ3VsYXRvcnkgYXBwcm92YWwgKGUuZy4sIGJ5IHRoZSBGREEpLiBUaGlzIGlzIHRoZSBjb25maXJtYXRvcnkgc3RhZ2Ugd2hlcmUgaHlwb3RoZXNpcyB0ZXN0aW5nIGlzIGZvcm1hbGx5IGFwcGxpZWQgdG8gcHJvdmUgZWZmaWNhY3kuDQoNCg0KKipSZWd1bGF0b3J5IFJldmlldyBhbmQgQXBwcm92YWwqKg0KDQoqIEFmdGVyIFBoYXNlIDMsIGFsbCBkYXRhIGFyZSBjb21waWxlZCBhbmQgc3VibWl0dGVkIHRvIHJlZ3VsYXRvcnkgYXV0aG9yaXRpZXMgKGUuZy4sIEZEQSwgRU1BKSBmb3IgcmV2aWV3IGFuZCBhIGRlY2lzaW9uIG9uIG1hcmtldGluZyBhcHByb3ZhbC4NCg0KDQoqKlBoYXNlIDQ6IFBvc3QtTWFya2V0aW5nIFN1cnZlaWxsYW5jZSoqIC0gT25nb2luZyBtb25pdG9yaW5nIGZvciBsb25nLXRlcm0gZWZmZWN0cyBvY2N1cnMgYWZ0ZXIgdGhlIGRydWcgaXMgb24gdGhlIG1hcmtldC4gDQoNCiogKipQcmltYXJ5IEdvYWwqKjogTW9uaXRvciB0aGUgZHJ1ZydzIGxvbmctdGVybSBzYWZldHksIGVmZmVjdGl2ZW5lc3MsIGFuZCBvcHRpbWFsIHVzZSBpbiB0aGUgZ2VuZXJhbCBwb3B1bGF0aW9uLg0KDQoqICoqUGFydGljaXBhbnRzKio6IFRob3VzYW5kcyBvZiBwYXRpZW50cyBpbiByZWFsLXdvcmxkIHNldHRpbmdzIGFmdGVyIHRoZSBkcnVnIGlzIHB1YmxpY2x5IGF2YWlsYWJsZS4NCg0KKiAqKktleSBGb2N1cyoqOiBEZXRlY3QgcmFyZSBvciBsb25nLXRlcm0gYWR2ZXJzZSBlZmZlY3RzIGFuZCBzdHVkeSBuZXcgcG9wdWxhdGlvbnMgb3IgdXNlcy4NCg0KDQojIyBXaGVuIGFuZCBIb3cgSHlwb3RoZXNpcyBUZXN0aW5nIElzIFVzZWQNCg0KVGhlIHVzZSBvZiBoeXBvdGhlc2lzIHRlc3RpbmcgaW4gUGhhc2UgSSBhbmQgUGhhc2UgSUkgdHJpYWxzIGlzIGZ1bmRhbWVudGFsbHkgZGlmZmVyZW50IGZyb20gaXRzIHJvbGUgaW4gUGhhc2UgSUlJLiBUaGUgcHJpbWFyeSBnb2FscyBhcmUgc2FmZXR5LCBkb3NpbmcsIGFuZCBlc3RpbWF0aW5nIGVmZmVjdHPigJRub3QgY29uZmlybWluZyB0aGVtIHdpdGggc3RhdGlzdGljYWwgcmlnb3IuDQoNCiogKipQaGFzZSBJKio6IEh5cG90aGVzaXMgdGVzdGluZyBpcyBtaW5pbWFsLiBUaGUgZm9jdXMgaXMgb24gZXN0aW1hdGlvbiBhbmQgc2FmZXR5Lg0KDQoqICoqUGhhc2UgSUkqKjogSHlwb3RoZXNpcyB0ZXN0aW5nIGlzIGEgY3JpdGljYWwgZGVjaXNpb24tbWFraW5nIHRvb2wgYnV0IGlzIGFwcGxpZWQgd2l0aCBleHBsb3JhdG9yeSBpbnRlbnQuIEEgcG9zaXRpdmUgcmVzdWx0IGlzIGEgc2lnbmFsIHRvIG1vdmUgZm9yd2FyZCwgbm90IGEgY2xhaW0gZm9yIGFwcHJvdmFsLg0KDQoqICoqUGhhc2UgSUlJKio6IEh5cG90aGVzaXMgdGVzdGluZyBpcyB0aGUgcHJlLXNwZWNpZmllZCwgcmlnb3JvdXMgZXhwZXJpbWVudCBkZXNpZ25lZCB0byBjb25maXJtIHRoZSBkZWZpbml0aXZlIGh5cG90aGVzaXMgZm9yIHJlZ3VsYXRvcnMuDQoNCkluIHRlcm1zIG9mIHN0YXRpc3RpY2FsIHJvbGUgYW5kIHJpZ29yLCAqKmh5cG90aGVzaXMgdGVzdGluZyoqIGluIFBoYXNlIEkvSUkgdHJpYWxzIGlzICoqZmxleGlibGUqKiwgd2l0aCB0aGUgVHlwZSBJIGVycm9yIHJhdGUgKCRcYWxwaGEkKSBvZnRlbiBub3Qgc3RyaWN0bHkgY29udHJvbGxlZC4gSW4gb3RoZXIgd29yZHMsIGl0IGlzIGFuIGluZm9ybWFsIHRvb2wgdXNlZCBwcmltYXJpbHkgZm9yIGludGVybmFsIGRlY2lzaW9uLW1ha2luZyBhbmQgc2lnbmFsIGRldGVjdGlvbi4gSW4gY29udHJhc3QsICoqaHlwb3RoZXNpcyB0ZXN0aW5nKiogaW4gKipQaGFzZSBJSUkqKiBpcyBzdHJpY3Q6IHRoZSBUeXBlIEkgZXJyb3IgKCRcYWxwaGEkKSBpcyBzdHJvbmdseSBjb250cm9sbGVkLiBJdCBpcyBhIGZvcm1hbCwgbWFuZGF0b3J5LCBhbmQgZGVmaW5pdGl2ZSBwcm9jZXNzIHVzZWQgdG8gY29uZmlybSBlZmZpY2FjeSBhbmQgc2FmZXR5IGZvciByZWd1bGF0b3J5IGFwcHJvdmFsLg0KDQoNClRvIG91dGxpbmUgb2Ygb3ZlcmFyY2hpbmcgZnJhbWV3b3JrIG9mIHJpZ29yb3VzIGh5cG90aGVzaXMgdGVzdGluZywgd2UgdXNlIGZvY3VzIG9uIGl0cyBhcHBsaWNhdGlvbiBpbiBwaGFzZSBJSUkgdHJpYWwuIFdlIGtub3cgdGhhdCBhbGwgY29uZmlybWF0b3J5IGNsaW5pY2FsIHRyaWFscyBhcmUgZGVzaWduZWQgYXMgY29udHJvbGxlZCBleHBlcmltZW50cyB3aXRoOg0KDQoqIEEgcHJlLXNwZWNpZmllZCBwcmltYXJ5IG91dGNvbWUgKGUuZy4sIHR1bW9yIHNpemUgcmVkdWN0aW9uLCBzdXJ2aXZhbCB0aW1lLCBzeW1wdG9tIHNjb3JlKS4NCg0KKiBBIG51bGwgaHlwb3RoZXNpcyAoSG8pIHRoYXQgdGhlIG5ldyB0cmVhdG1lbnQgaXMgbm8gYmV0dGVyIHRoYW4gdGhlIGNvbnRyb2wgKHBsYWNlYm8gb3Igc3RhbmRhcmQgb2YgY2FyZSkuDQoNCiogQW4gYWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyAoSGEpIHRoYXQgdGhlIG5ldyB0cmVhdG1lbnQgaXMgYmV0dGVyLg0KDQoqIEEgcHJlLWRlZmluZWQgc2lnbmlmaWNhbmNlIGxldmVsICgkXGFscGhhJCksIGFsbW9zdCBhbHdheXMgJFxhbHBoYSA9IDAuMDUkIGZvciB0aGUgcHJpbWFyeSBlbmRwb2ludC4NCg0KKiBBIHByZS1zcGVjaWZpZWQgc3RhdGlzdGljYWwgdGVzdCAodC10ZXN0LCBsb2ctcmFuayB0ZXN0LCBjaGktc3F1YXJlLCBldGMuKSBhbmQgYW5hbHlzaXMgcGxhbi4NCg0KDQoqKkNvbW1lbnQqKjogSW4gdGhlIGNvbnRleHQgb2YgY29uZmlybWF0b3J5IGNsaW5pY2FsIHRyaWFscywgdGhlIHByZS1kZWZpbmVkIHNpZ25pZmljYW5jZSBsZXZlbCAoYWxwaGEsICRcYWxwaGEkKSBhbmQgVHlwZSBJIGVycm9yIGFyZSBpbnRpbWF0ZWx5IHJlbGF0ZWQgYnV0IGRpc3RpbmN0IGNvbmNlcHRzLiBJbiB0aGUgKipzaW1wbGVzdCBmaXhlZCBkZXNpZ24qKjogKipCeSBzZXR0aW5nICRcYWxwaGEgPSAwLjA1JCwgeW91IGFyZSBkZXNpZ25pbmcgdGhlIHRyaWFsIHRvIGhhdmUgYSBtYXhpbXVtIGFsbG93YWJsZSBUeXBlIEkgZXJyb3IgcmF0ZSBvZiA1JSoqLiBJbiBvdGhlciB3b3JkcywgPGZvbnQgY29sb3IgPSAicmVkIj4qaWYgeW91IGZvbGxvdyB0aGUgc3RhdGlzdGljYWwgcGxhbiBleGFjdGx5LCB0aGUgYWN0dWFsIHByb2JhYmlsaXR5IG9mIG1ha2luZyBhIFR5cGUgSSBlcnJvciAoZmFsc2VseSByZWplY3RpbmcgdGhlIG51bGwpIGlzIGNvbnRyb2xsZWQgYXQgMC4wNS4qPC9mb250Pg0KDQoNCg0KDQojIElsbHVzdHJhdGl2ZSBFeGFtcGxlcw0KDQpUaGlzIHNlY3Rpb24gdXNlcyB0d28gc2ltcGxlIHRlc3RzIGFib3V0IHBvcHVsYXRpb25zIHRvIGlsbHVzdHJhdGUgdGhlIHN0ZXBzIHN1Z2dlc3RlZCBmb3IgaHlwb3RoZXNpcyB0ZXN0aW5nLiANCg0KDQojIyBFeGFtcGxlIDE6IE9uZS1TYW1wbGUgdC10ZXN0DQoNCg0KKipQcm9ibGVtKio6IEEgY29tcGFueSBjbGFpbXMgdGhlaXIgZW5lcmd5IGRyaW5rIGluY3JlYXNlcyBJUSAoJFxtdSA9IDEwMCQpLiBTYW1wbGUgb2YgMjUgdXNlcnMgaGFzIG1lYW4gSVEgPSAxMDYsIFNEID0gMTUuIFRlc3QgYXQgJFxhbHBoYSA9IDAuMDUkLg0KDQoqKk1hbnVhbCBDYWxjdWxhdGlvbioqOg0KDQoqICoqU3RlcCAxKio6IFRoZSBpbmZvcm1hdGlvbiBpcyBjbGVhcmx5IGdpdmVuIGluIHRoZSBwcm9ibGVtLiAkbiA9IDI1LCBcYmFye3h9ID0gMTA2LCBzID0gMTUsIFxtdV8wID0gMTAwJCwgYW5kICRcYWxwaGEgPSAwLjA1JC4gVGhlIGNsYWltICgqaW5jcmVhc2UgSVEqKSBpcyB0aGF0ICRcbXUgPiAxMDAkDQoNCg0KKiAqKlN0ZXAgMioqOiBIeXBvdGhlc2VzDQogICsgJEhfMDogXG11ID0gMTAwJCAobm8gZWZmZWN0KQ0KICArICRIXzE6IFxtdSA+IDEwMCQgKG9uZS10YWlsZWQsIGRyaW5rIGluY3JlYXNlcyBJUSkNCg0KDQoqICoqU3RlcCAzKio6IFRlc3QgU3RhdGlzdGljDQoNCiQkbiA9IDI1LCBcYmFye3h9ID0gMTA2LCBzID0gMTUsIFxtdV8wID0gMTAwJCQNCiQkdCA9IFxmcmFjezEwNiAtIDEwMH17MTUvXHNxcnR7MjV9fSA9IFxmcmFjezZ9ezE1LzV9ID0gXGZyYWN7Nn17M30gPSAyLjAkJA0KDQokJGRmID0gbiAtIDEgPSAyNCQkDQoNCg0KKiAqKlN0ZXAgNCoqOiBDcml0aWNhbCBWYWx1ZSBmb3IgdGhpcyByaWdodC10YWlsZWQgdGVzdCBpcw0KDQokJHRfe1xhbHBoYT0wLjA1LCBkZj0yNH0gPSAxLjcxMSQkDQoNCiogKipTdGVwIDUqKjogRGVjaXNpb24gLSBzaW5jZSAkdCA9IDIuMCA+IDEuNzExJCwgcmVqZWN0ICRIXzAkLg0KDQoqICoqU3RlcCA2Kio6IEludGVycHJldGF0aW9uIC0gRXZpZGVuY2Ugc3VnZ2VzdHMgZHJpbmsgaW5jcmVhc2VzIElRLg0KDQoNCioqVmVyaWZpY2F0aW9uIFVzaW5nIFIqKjoNCg0KYGBge3J9DQojIE9uZS1zYW1wbGUgdC10ZXN0IGluIFINCnNldC5zZWVkKDEyMykNCnNpbXVsYXRlZF9pcSA8LSBybm9ybSgyNSwgbWVhbiA9IDEwNiwgc2QgPSAxNSkNCnJlc3VsdCA8LSB0LnRlc3Qoc2ltdWxhdGVkX2lxLCBtdSA9IDEwMCwgDQogICAgICAgICAgICAgICAgIGFsdGVybmF0aXZlID0gImdyZWF0ZXIiKQ0KDQojIE91dHB1dA0KcHJpbnQocmVzdWx0KQ0KIyMjDQpjYXQoIlxuTWFudWFsIHQtdmFsdWU6IDIuMCIsDQogICAgIlxuUiB0LXZhbHVlOiIsIHJvdW5kKHJlc3VsdCRzdGF0aXN0aWMsIDMpLA0KICAgICJcbkNyaXRpY2FsIHQtdmFsdWUgKDAuMDUpOiAxLjcxMSIsDQogICAgIlxuUiBwLXZhbHVlOiIsIHJvdW5kKHJlc3VsdCRwLnZhbHVlLCA0KSkNCmBgYA0KDQpcDQoNCiMjIEV4YW1wbGUgMjogVHdvLVNhbXBsZSB0LXRlc3QNCg0KKipQcm9ibGVtKio6IENvbXBhcmUgZXhhbSBzY29yZXMgZm9yIHR3byB0ZWFjaGluZyBtZXRob2RzIHdpdGggdGhlIGZvbGxvd2luZyBnaXZlIGluZm9ybWF0aW9uOg0KDQoqICoqTWV0aG9kIEEqKjogJG5fMT0zMCQsICRcYmFye3h9XzE9NzgkLCAkc18xPTgkDQoqICoqTWV0aG9kIEIqKjogJG5fMj0zNSQsICRcYmFye3h9XzI9NzIkLCAkc18yPTEwJA0KKiAqKlRlc3QqKiBhdCAkXGFscGhhPTAuMDUkIGlmIG1ldGhvZHMgZGlmZmVyLg0KDQoqKk1hbnVhbCBDYWxjdWxhdGlvbioqOg0KDQoNCiogKipTdGVwIDEqKjogVGhlIGdpdmVuIGluZm9ybWF0aW9uIGlzIGNsZWFybHkgbGlzdGVkIGFib3ZlLiBUaGUgY2xhaW0gaXMgJFxtdV8xIC1cbXVfMiBcbmUgMCQNCg0KDQoqICoqU3RlcCAyOiBIeXBvdGhlc2VzKioNCiAgKyAkSF8wOiBcbXVfMSA9IFxtdV8yJA0KICArICRIXzE6IFxtdV8xIFxuZXEgXG11XzIkDQoNCg0KKiAqKlN0ZXAgMyoqOiBQb29sZWQgVmFyaWFuY2UNCg0KJCRzX3BeMiA9IFxmcmFjeyhuXzEtMSlzXzFeMiArIChuXzItMSlzXzJeMn17bl8xK25fMi0yfSQkDQoNCiQkPSBcZnJhY3soMjkpKDY0KSArICgzNCkoMTAwKX17NjN9JCQNCiQkPSBcZnJhY3sxODU2ICsgMzQwMH17NjN9ID0gXGZyYWN7NTI1Nn17NjN9ID0gODMuNDMkJA0KDQokJHNfcCA9IFxzcXJ0ezgzLjQzfSA9IDkuMTM0JCQNCg0KDQoqICoqU3RlcCA0OiBUZXN0IFN0YXRpc3RpYyoqDQoNCiQkdCA9IFxmcmFje1xiYXJ7eH1fMSAtIFxiYXJ7eH1fMn17c19wXHNxcnR7XGZyYWN7MX17bl8xfSArIFxmcmFjezF9e25fMn19fSQkDQokJD0gXGZyYWN7NzggLSA3Mn17OS4xMzRcc3FydHtcZnJhY3sxfXszMH0gKyBcZnJhY3sxfXszNX19fSQkDQokJD0gXGZyYWN7Nn17OS4xMzRcc3FydHswLjAzMzMgKyAwLjAyODZ9fSQkDQoNCiQkPSBcZnJhY3s2fXs5LjEzNFxzcXJ0ezAuMDYxOX19JCQNCg0KJCQ9IFxmcmFjezZ9ezkuMTM0IFx0aW1lcyAwLjI0ODh9ID0gXGZyYWN7Nn17Mi4yNzN9ID0gMi42MzkkJA0KDQokJGRmID0gbl8xICsgbl8yIC0gMiA9IDYzJCQNCg0KKiAqKlN0ZXAgNSoqOiBDcml0aWNhbCBWYWx1ZSBmb3IgdGhpcyB0d28tdGFpbGVkIHRlc3QNCg0KJCR0X3tcYWxwaGE9MC4wNSxkZj02M30gXGFwcHJveCAyLjAwMCQkDQoNCiogKipTdGVwIDYqKjogRGVjaXNpb24gLSBTaW5jZSAkfHR8ID0gMi42MzkgPiAyLjAwMCQsIHJlamVjdCAkSF8wJA0KDQoNCioqVmVyaWZpY2F0aW9uIFVzaW5nIFIqKg0KDQpgYGB7cn0NCiMgVHdvLXNhbXBsZSB0LXRlc3QgaW4gUg0Kc2V0LnNlZWQoMTIzKQ0KbWV0aG9kX0EgPC0gcm5vcm0oMzAsIG1lYW4gPSA3OCwgc2QgPSA4KQ0KbWV0aG9kX0IgPC0gcm5vcm0oMzUsIG1lYW4gPSA3Miwgc2QgPSAxMCkNCg0KIyBFcXVhbCB2YXJpYW5jZSBhc3N1bWVkDQpyZXN1bHQgPC0gdC50ZXN0KG1ldGhvZF9BLCBtZXRob2RfQiwgDQogICAgICAgICAgICAgICAgIHZhci5lcXVhbCA9IFRSVUUsDQogICAgICAgICAgICAgICAgIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpDQoNCnByaW50KHJlc3VsdCkNCmBgYA0KDQoNCg0KIyAgUG93ZXIgQW5hbHlzaXMgDQoNCkVmZmVjdCBzaXplLCBzdGF0aXN0aWNhbCBwb3dlciwgYW5kIHNhbXBsZSBzaXplIGRldGVybWluYXRpb24gZm9ybSB0aGUgc3RhdGlzdGljYWwgdHJpbml0eSBmb3IgZGVzaWduaW5nIHJvYnVzdCBleHBlcmltZW50cyBhbmQgc3R1ZGllcy4gV2Ugd2lsbCBmaXJzdCBicmllZmx5IG91dGxpbmUgdGhlIGNvbXBvbmVudHMgb2YgdGhpcyB0cmluaXR5IGJlZm9yZSBwcmVzZW50aW5nIGFuIGV4YW1wbGUuDQoNCiMjIEVmZmVjdCBTaXplDQoNCioqRWZmZWN0IFNpemUqKiBpcyBhIHF1YW50aXRhdGl2ZSBtZWFzdXJlIG9mIHRoZSBtYWduaXR1ZGUgb2YgdGhlIHBoZW5vbWVub24gb3IgZGlmZmVyZW5jZSB5b3UgYXJlIHN0dWR5aW5nLiBJdCdzIGEgc3RhbmRhcmRpemVkLCBzY2FsZS1mcmVlIG1ldHJpYyB0aGF0IGFuc3dlcnMgIioqaG93IG11Y2g/KioiIHJhdGhlciB0aGFuIGp1c3QgIioqaXMgdGhlcmUgYW4gZWZmZWN0Kio/Ii4gV2hpbGUgKipzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UgKHAtdmFsdWVzKSoqIGFuc3dlcnMgIioqSXMgdGhlcmUgYW4gZWZmZWN0Kio/IiwgKiplZmZlY3Qgc2l6ZSoqIGFuc3dlcnMgIioqSG93IGxhcmdlKiogaXMgdGhlIGVmZmVjdD8iDQoNCkluIG90aGVyIHdvcmRzLDxmb250IGNvbG9yID0gImRhcmtyZWQiPiAqKmVmZmVjdCBzaXplKiogcXVhbnRpZmllcyB0aGUgbWFnbml0dWRlIG9mIHByYWN0aWNhbCBpbXBvcnRhbmNlIGFuZCAqKnAtdmFsdWUqKiBtZWFzdXJlcyB0aGUgc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlLjwvZm9udD4NCg0KXA0KDQpUaGUgKiplZmZlY3Qgc2l6ZSoqIGlzIGRlZmluZWQgZGlmZmVyZW50bHkgYWNjb3JkaW5nIHRvIHRoZSBhY3R1YWwgdGVzdHMuIFNvbWUgY29tbW9uIHR5cGVzIGFyZSBsaXN0ZWQgYmVsb3c6DQoNCiogKipGb3IgRGlmZmVyZW5jZXMgYmV0d2VlbiBHcm91cHMqKjogQ29oZW4ncyAqZCogKGBtZWFuIGRpZmZlcmVuY2UgLyBwb29sZWQgc3RhbmRhcmQgZGV2aWF0aW9uYCAkPShcbXVfMS1cbXVfMikvXHNpZ21hJCkuIFNtYWxsIH4wLjIsIE1lZGl1bSB+MC41LCBMYXJnZSB+MC44Lg0KDQoqICoqRm9yIEFzc29jaWF0aW9ucyoqOiBQZWFyc29uJ3MgKnIqIChjb3JyZWxhdGlvbikuIFNtYWxsIH4wLjEsIE1lZGl1bSB+MC4zLCBMYXJnZSB+MC41Lg0KDQoqICoqRm9yIFByb3BvcnRpb25zKio6IFJpc2sgZGlmZmVyZW5jZSwgb2RkcyByYXRpbywgcmlzayByYXRpby4gVGhlc2UgaW1wb3J0YW50IG1lYXN1cmUgd2lsbCBiZSBkaXNjdXNzZWQgaW4gc3Vic2VxdWVudCBjb3Vyc2VzDQoNCiogKipGb3IgVmFyaWFuY2UgRXhwbGFpbmVkKio6ICRSXjIkLC4NCg0KXA0KDQoqKktleSBQcmluY2lwbGUqKjogV2UgbXVzdCBzcGVjaWZ5IGEgTWluaW11bSBDbGluaWNhbGx5L1ByYWN0aWNhbGx5IEltcG9ydGFudCBFZmZlY3QuIFRoaXMgaXMgdGhlIHNtYWxsZXN0IGVmZmVjdCB0aGF0IHdvdWxkIGJlIG1lYW5pbmdmdWwgaW4gcmVhbC13b3JsZCBjb250ZXh0LiAqKkl0J3Mgbm90IGEgc3RhdGlzdGljYWwgY2hvaWNlLCBidXQgYSBzdWJqZWN0LW1hdHRlciBvbmUqKi4NCg0KDQojIyBTdGF0aXN0aWNhbCBQb3dlcg0KDQpBcyBkaXNjdXNzZWQgZWFybGllciwgdGhlIHByb2JhYmlsaXR5IHRoYXQgb3VyIHRlc3Qgd2lsbCBjb3JyZWN0bHkgKipyZWplY3QqKiB0aGUgbnVsbCBoeXBvdGhlc2lzIChlLmcsIHRoZXJlIGlzIG5vIHRyZWF0bWVudCBlZmZlY3QpIHdoZW4gdGhlIGFsdGVybmF0aXZlIGh5cG90aGVzaXMgKHRoZXJlIGlzIHRyZWF0bWVudCBlZmZlY3QpIGlzIHRydWUuIEluIG90aGVyIHdvcmRzLCB0aGUgcG93ZXIgaXMgdGhlIHByb2JhYmlsaXR5IG9mIGRldGVjdCB0aGUgdHJ1ZSB0cmVhdG1lbnQgZWZmZWN0LiANCg0KDQoqICRcdGV4dHtQb3dlcn0gPSBQKFx0ZXh0e1JlamVjdCBIb30gfCBcdGV4dHtIYX0pID0gMSAtIFAoXHRleHR7Q29uY2x1ZGUgSG99fFx0ZXh0e0hhfSkgPSAxIC0gXGJldGEkLCB3aGVyZSAkXGJldGEgPSBQKFx0ZXh0e0NvbmNsdWRlIEhvfXxcdGV4dHtIYX0pJCBpcyB0aGUgVHlwZSBJSSBlcnJvciByYXRlIChmYWxzZSBuZWdhdGl2ZSByYXRlKS4NCg0KKiAqQ29udmVudGlvbio6IEEgY29tbW9uIHRhcmdldCBpcyA4MCUgcG93ZXIgKCRcYmV0YSQgPSAwLjIwKS4gRm9yIG1vcmUgc2Vuc2l0aXZlIG9yIGhpZ2gtc3Rha2VzIHN0dWRpZXMsIDkwJSBpcyBvZnRlbiB1c2VkLg0KDQoqKkluIHBsYWluIEVuZ2xpc2gqKjogRm9yIGEgKipwcmVzZXQgZWZmZWN0Kiogc2l6ZSwgcG93ZXIgaXMgdGhlIGNoYW5jZSB0aGUgc2FtcGxlIChiYXNlZCBvbiBhbiBleHBlcmltZW50KSB3aWxsIHN1Y2Nlc3NmdWxseSBkZXRlY3QgaXQuIExvdyBwb3dlciBtZWFucyB0aGUgc3R1ZHkgaGFzIGEgbG93IGNoYW5jZSBvZiBmaW5kaW5nIGEgcmVhbCBlZmZlY3QsICoqZXZlbiBpZiBvbmUgZXhpc3RzKiouIA0KDQoNCiMjIFNhbXBsZSBTaXplIERldGVybWluYXRpb24NCg0KKipTYW1wbGUgU2l6ZSBEZXRlcm1pbmF0aW9uKiogaXMgdGhlIHByb2Nlc3Mgb2YgY2FsY3VsYXRpbmcgdGhlIG51bWJlciBvZiBwYXJ0aWNpcGFudHMgb3Igb2JzZXJ2YXRpb25zIG5lZWRlZCBpbiBhIHN0dWR5ICoqdG8gYWNoaWV2ZSBhIHNwZWNpZmllZCBwb3dlcioqIGZvciBhIGdpdmVuICoqZWZmZWN0IHNpemUqKiBhbmQgKipzaWduaWZpY2FuY2UgbGV2ZWwqKi4gU2FtcGxlIHNpemUgZGV0ZXJtaW5hdGlvbiBpcyB0aGUgZm91bmRhdGlvbiBvZiByaWdvcm91cyBjbGluaWNhbCByZXNlYXJjaC4gSXQgZW5zdXJlcyBzdHVkaWVzIGFyZSBwcm9wZXJseSBzaXplZCB0byBkZXRlY3QgbWVhbmluZ2Z1bCBlZmZlY3RzIHdpdGhvdXQgZXhwb3NpbmcgcGFydGljaXBhbnRzIHRvIHVubmVjZXNzYXJ5IHJpc2sgb3Igd2FzdGluZyByZXNvdXJjZXMuDQoNCkl0J3MgY2FsY3VsYXRpbmcgIkhvdyBtYW55IHBlb3BsZSBkbyB3ZSBuZWVkIHRvIHRlc3QgdG8gaGF2ZSBhIGdvb2QgY2hhbmNlIG9mIHByb3Zpbmcgb3VyIHRyZWF0bWVudCB3b3JrcywgYXNzdW1pbmcgaXQgYWN0dWFsbHkgd29ya3MgYXMgd2VsbCBhcyB3ZSBob3BlPyINCg0KVGhlIGdlbmVyYWwgbG9naWNhbCBwcm9jZXNzIGZvciBkZXRlcm1pbmUgdGhlIHNhbXBsZSBzaXplIGF0IGEgZ2l2ZW4gc2lnbmlmaWNhbnQgbGV2ZWwgKCRcYWxwaGEkKSBpcyB0bw0KDQoqIHN0YXJ0IHdpdGggdGhlIHNtYWxsZXN0IGVmZmVjdCAoc2l6ZSkgdGhhdCBtYXR0ZXJzOw0KKiBkZWNpZGUgdGhlIHBvd2VyIChpLmUuLCBob3cgc3VyZSB3ZSBuZWVkIHRvIGJlIGFibGUgdG8gZGV0ZWN0IHRoZSBlZmZlY3QpOw0KKiBjYWxjdWxhdGUgdGhlIHNhbXBsZSBzaXplIHJlcXVpcmVkLg0KDQoNCiMjIFRoZSBUcmluaXR5IFJlbGF0aW9uc2hpcA0KDQpUaGUgKip0cmluaXR5IHJlbGF0aW9uc2hpcCoqIHJlZmVycyB0byB0aGUgZnVuZGFtZW50YWwgaW50ZXJkZXBlbmRlbmNlIGFtb25nIGVmZmVjdCBzaXplLCBzdGF0aXN0aWNhbCBwb3dlciwgYW5kIHNhbXBsZSBzaXplIGluIGh5cG90aGVzaXMgdGVzdGluZy4gT25jZSB3ZSBmaXggYW55IHR3byBvZiB0aGVzZSwgdGhlIHRoaXJkIGlzIGVzc2VudGlhbGx5IGRldGVybWluZWQgKGdpdmVuIGEgc2lnbmlmaWNhbmNlIGxldmVsICRcYWxwaGEkIGFuZCBhIHRlc3QvbW9kZWwpLg0KDQpUaGUgbmV4dCBmZXcgYnVsbGV0IHBvaW50cyBleHBsYWluIGhvdyB0aGUgdGhyZWUgY29tcG9uZW50cyBpbnRlcmFjdC4gVG8gZmFjaWxpdGF0ZSB1bmRlcnN0YW5kaW5nLCB3ZSB1c2UgYW5pbWF0ZWQgZmlndXJlcyBiYXNlZCBvbiBvbmUtc2FtcGxlIHRlc3Qgb2YgYSBub3JtYWwgcG9wdWxhdGlvbiBtZWFuIHdpdGgga25vdyBwb3B1bGF0aW9uIHN0YW5kYXJkIGRldmlhdGlvbiAkXHNpZ21hJDoNCg0KJCQNCkhfMDogXG11IFxsZSBcbXVfMCBccXVhZCBcdGV4dHt2LnMufSAgXHF1YWQgSF9hOiAgICBcbXUgPiBcbXVfMA0KJCQNClRoZSBlZmZlY3Qgc2l6ZSBpcyAkKFxtdSAtIFxtdV8wKS8oXHNpZ21hL1xzcXJ0e259KSQgYW5kIHRoZSB0ZXN0IHN0YXRpc3RpYyAkVD0oXGJhcnt4fS1cbXVfMCkvKFxzaWdtYS9cc3FydHtufSkkLg0KDQoNCiogKipFZmZlY3QgU2l6ZSoqICRcTG9uZ2xlZnRyaWdodGFycm93JCAqKlNhbXBsZSBTaXplKioNCiAgKyA8Zm9udCBjb2xvciA9ICJyZWQiPioqQ2F1dGlvbioqPC9mb250PjogPGZvbnQgY29sb3I9ICJibHVlIj5FZmZlY3Qgc2l6ZSBpcyAqKmluZGVwZW5kZW50IG9mKiogc2FtcGxlIHNpemUuIEhvd2V2ZXIsIGl0IGltcGFjdHMgdGhlIHBvd2VyIHRvIGRldGVjdCB0aGUgZWZmZWN0IHNpemUuIFRvIGJlIG1vcmUgc3BlY2lmaWMsICoqbGFyZ2VyIHNhbXBsZSBzaXplcyBpbmNyZWFzZSB0aGUgcG93ZXIgdG8gZGV0ZWN0IGEgZ2l2ZW4gZWZmZWN0IHNpemUsIHdoaWxlIHNtYWxsZXIgc2FtcGxlIHNpemVzIHJlZHVjZSBpdCoqLjwvZm9udD4gDQogICAgLSAgU21hbGxlciBlZmZlY3QgJFxSaWdodGFycm93JCBsYXJnZXIgc2FtcGxlIG5lZWRlZA0KICAgIC0gIExhcmdlciBlZmZlY3QgJFxSaWdodGFycm93JCBzbWFsbGVyIHNhbXBsZSBzdWZmaWNpZW50DQogICsgRGV0ZWN0aW5nIGEgdGlueSBlZmZlY3QgcmVxdWlyZXMgYSBsb3Qgb2YgZGF0YS4NCg0KKiAqKlNhbXBsZSBTaXplKiogJFxMb25nbGVmdHJpZ2h0YXJyb3ckICoqUG93ZXIqKg0KICArIExhcmdlciBzYW1wbGUgc2l6ZXMgcmVkdWNlIHRoZSBkZW5vbWluYXRvciBpbiB0aGUgdGVzdCBzdGF0aXN0aWMsIHdoaWNoIGRlY3JlYXNlcyB0aGUgdmFyaWFuY2Ugb2YgdGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbnMgdW5kZXIgJEhfMCQgICBhbmQgJEhfYSQgKGkuZS4sIHRoZSBkZW5zaXR5IGN1cnZlcyBiZWNvbWUgbmFycm93ZXIpLiBUaGlzIGluIHR1cm4gaW5jcmVhc2VzIHBvd2VyLg0KICAgIC0gTGFyZ2VyIHNhbXBsZSAkXFJpZ2h0YXJyb3ckIGhpZ2hlciBwb3dlcg0KICAgIC0gU21hbGxlciBzYW1wbGUgJFxSaWdodGFycm93JCBsb3dlciBwb3dlcg0KICArIFBvd2VyIGluY3JlYXNlcyBtb25vdG9uaWNhbGx5IHdpdGggbi4NCg0KYGBge3IgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNzAlIn0NCmluY2x1ZGVfZ3JhcGhpY3MoInBvd2VyX2J5X3Zhci5naWYiKQ0KYGBgDQoNCg0KKiAqKkVmZmVjdCBTaXplKiogJFxMb25nbGVmdHJpZ2h0YXJyb3ckICoqUG93ZXIqKg0KICArIExhcmdlciBlZmZlY3QgJFxSaWdodGFycm93JCBoaWdoZXIgcG93ZXIgKGZvciBmaXhlZCBuKQ0KICArIFNtYWxsZXIgZWZmZWN0ICRcUmlnaHRhcnJvdyQgbG93ZXIgcG93ZXINCiAgKyBTdHJvbmdlciBzaWduYWxzIGFyZSBlYXNpZXIgdG8gZGV0ZWN0Lg0KDQpgYGB7ciBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSI3MCUifQ0KaW5jbHVkZV9ncmFwaGljcygicG93ZXJfYnlfbWVhbi5naWYiKQ0KYGBgDQoNCg0KIyMgUG93ZXIgQ2FsY3VsYXRpb24NCg0KVGhlICoqbm9uY2VudHJhbGl0eSBwYXJhbWV0ZXIqKiAoTkNQKSBpcyBhIHN0YW5kYXJkaXplZCBtZWFzdXJlIG9mIGhvdyBmYXIgdGhlIGFsdGVybmF0aXZlIGh5cG90aGVzaXMgKCRIX2EkKSBpcyBmcm9tIHRoZSBudWxsIGh5cG90aGVzaXMgKCRIXzAkKSBpbiB0ZXJtcyBvZiBzdGFuZGFyZCBlcnJvcnMgb2YgdGhlIGNvcnJlc3BvbmRpbmcgc2FtcGxlIHN0YXRpc3RpY3MuIFRoZSBhY3R1YWwgZm9ybXVsYSBvZiBOQ1AgaXMgZGVwZW5kZW50IG9uIHRoZSBzcGVjaWZpYyB0ZXN0LiBUaGUgZm9sbG93aW5nIGFyZSBmZXcgTkNQcyBmb3IgdGVzdHMgdGhhdCBjb21tb25seSB1c2VkIGluIHBvd2VyIGFuYWx5c2lzDQoNCiogKipPbmUtc2FtcGxlIHQtdGVzdCoqOiAgJEhfMDokICRcbXUgPSBcbXVfMCQgdnMgJEhfYTokICAkXG11IFxuZSAoPiwgPCkgXHF1YWRcbXVfMCQNCiAgKyBTdGFuZGFyZCBlcnJvciBvZiBzYW1wbGUgc3RhdGlzdGljICRcYmFye3h9JCBpcyAkXHNpZ21hL1xzcXJ0e259JA0KICArIERpZmZlcmVuY2UgYmV0d2VlbiAkSF9hJCBhbmQgJEhfMCQ6ICAkXGRlbHRhID0gXG11IC0gXG11XzAkOw0KICArIFRoZSBOQ1AgaXMgZGVmaW5lZCBieQ0KICANCiQkDQpcbGFtYmRhID0gXGZyYWN7XG11IC0gXG11XzB9e1xzaWdtYS9cc3FydHtufX0gXHF1YWQgXHRleHR7dGhpcyBpcyBkaWZmZXJzIHRoZSB0ZXN0IHN0YXRpc3RpY30gXHF1YWQgVCA9IFxmcmFje1xiYXJ7eH0tXG11XzB9e3MvXHNxcnR7bn19Lg0KJCQNCg0KKiAqKlR3by1zYW1wbGUgdC10ZXN0Kio6ICRIXzAkOiAkXG11XzEgLSBcbXVfMiA9IDAkICB2cyAgJEhfYSQ6ICRcbXVfMSAtIFxtdV8yIFxuZSAoPiwgPCkgXHF1YWQgMCQsIGJvdGggcG9wdWxhdGlvbiB2YXJpYW5jZXMgYXJlIHN1bW1lZCB0byBiZSBlcXVhbC4NCiAgKyBTdGFuZGFyZCBlcnJvciBvZiBzYW1wbGUgc3RhdGlzdGljICRcYmFye3h9XzEgLSBcYmFye3h9XzIkIGJhc2VkIG9uIHRoZSBwb29sZWQgc2FtcGxlIGlzICRcc2lnbWFfcC9cc3FydHsxL25fMSsxL25fMn0kDQogICsgRGlmZmVyZW5jZSBiZXR3ZWVuICRIX2EkIGFuZCAkSF8wJDogICRcZGVsdGEgPSAoXG11XzEgLSBcbXVfMiktMCA9IFxtdV8xIC0gXG11XzIkOw0KICArIFRoZSBOQ1AgaXMgZGVmaW5lZCBieQ0KDQokJA0KXGxhbWJkYSA9IFxmcmFje1xkZWx0YX17XHNpZ21hL1xzcXJ0ezEvbl8xKzEvbl8yfX0gXHF1YWQgXHRleHR7dGhpcyBpcyBkaWZmZXJzIHRoZSB0ZXN0IHN0YXRpc3RpY30gXHF1YWQgVCA9IFxmcmFje1xiYXJ7eH1fMS1cYmFye3h9XzJ9e3NfcC9cc3FydHsxL25fMSsxL25fMn19Lg0KJCQNCg0KV2Ugd2lsbCBub3QgbGlzdCB0aGUgbm9uY2VudHJhbGl0eSBwYXJhbWV0ZXJzIChOQ1BzKSBmb3Igb3RoZXIgdGVzdHMgZm9yIG5vdy4gVGhlIGtleSB0YWtlYXdheSBpcyB0byBhcHBseSB0aGUgZGVmaW5pdGlvbiBvZiB0aGUgTkNQIHRvIHRoZSBzcGVjaWZpYyBkaXN0cmlidXRpb24gaW4gb3JkZXIgdG8gZGVyaXZlIHRoZSBjb3JyZXNwb25kaW5nIE5DUCBmb3JtdWxhLiBOZXh0LCB3ZSB1c2UgdGhlIG9uZS1zYW1wbGUgdC10ZXN0IGFzIGFuIGV4YW1wbGUgdG8gZGVyaXZlIHRoZSBwb3dlciBmb3JtdWxhLg0KDQoNCkNvbnNpZGVyIG9uZS1zYW1wbGUgdHdvLXNpZGVkIHQtdGVzdDoNCg0KJCQNCkhfMDogXG11ID0gXG11XzAsIFxxcXVhZCBIXzE6IFxtdSBcbmVxIFxtdV8wIFxxdWFkIChcdGV4dHt0d28tc2lkZWR9KQ0KJCQNCg0KVGhlIHRlc3Qgc3RhdGlzdGljDQoNCiQkDQpUID0gXGZyYWN7XGJhcntYfSAtIFxtdV8wfXtTL1xzcXJ0e259fQ0KJCQNCg0KRWZmZWN0IHNpemUgKENvaGVuJ3MgJGQkIGZvciBvbmUgc2FtcGxlKToNCg0KJCQNClxkZWx0YSA9IFxmcmFje1xtdV8xIC0gXG11XzB9e1xzaWdtYX0NCiQkDQoNClVuZGVyICRIX2EkLCAkVCQgZm9sbG93cyBhIG5vbi1jZW50cmFsICR0JC1kaXN0cmlidXRpb24gd2l0aCAkbi0xJCBkZWdyZWVzIG9mIGZyZWVkb20gYW5kIG5vbi1jZW50cmFsaXR5IHBhcmFtZXRlcjoNCg0KDQokJA0KXGxhbWJkYSA9IFxzcXJ0e259XCxcZGVsdGEgPSBcc3FydHtufSBcY2RvdCBcZnJhY3tcbXVfMSAtIFxtdV8wfXtcc2lnbWF9ID0gXGZyYWN7XG11XzEgLSBcbXVfMH17XHNpZ21hL1xzcXJ0e259IH0NCiQkDQoNCg0KRm9yIHNpZ25pZmljYW5jZSBsZXZlbCAkXGFscGhhJDoNCg0KJCQNClx0ZXh0e1JlamVjdCB9IEhfMCBcdGV4dHsgaWYgfSB8VHwgPiB0X3sxLVxhbHBoYS8yLFwsIG4tMX0NCiQkDQoNCndoZXJlICR0X3sxLVxhbHBoYS8yLFwsIG4tMX0kIGlzIHRoZSAkMS1cYWxwaGEvMiQgcXVhbnRpbGUgb2YgdGhlIGNlbnRyYWwgJHQkLWRpc3RyaWJ1dGlvbiB3aXRoICRuLTEkIGRmLg0KDQoNCkxldCAkRl97dF97bi0xfShcbGFtYmRhKX0oXGNkb3QpJCBkZW5vdGUgdGhlIENERiBvZiB0aGUgbm9uLWNlbnRyYWwgJHQkLWRpc3RyaWJ1dGlvbiB3aXRoIGRmICRuLTEkIGFuZCBOQ1AgJFxsYW1iZGEkLiBUaGVuOg0KDQokJA0KXGJveGVke1x0ZXh0e1Bvd2VyfSA9IDEgLSBGX3t0X3tuLTF9KFxsYW1iZGEpfVxiaWdsKHRfezEtXGFscGhhLzIsXCwgbi0xfVxiaWdyKSArIEZfe3Rfe24tMX0oXGxhbWJkYSl9XGJpZ2woLXRfezEtXGFscGhhLzIsXCwgbi0xfVxiaWdyKX0NCiQkDQoNCmBgYHtyIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjY1JSJ9DQppbmNsdWRlX2dyYXBoaWNzKCJQb3dlci1EZW1vLnBuZyIpDQpgYGANCg0KVGhlIGFib3ZlIGZpZ3VyZSBzaG93cyB0aGF0LCBmb3IgYSB0d28tdGFpbGVkIHQtdGVzdCwgdGhlIHBvd2VyIGlzIHRoZSB0d28gdGFpbCBhcmVhcyAoc2hhZGVkIHJlZ2lvbiBpbiBkYXJrIHJlZCkgb2Ygbm9uLWNlbnRyYWwgdC1kaXN0cmlidXRpb24gZGVmaW5lZCBieSB0aGUgdHdvIGNyaXRpY2FsIHZhbHVlcyB1bmRlciB0aGUgcmVndWxhciB0LWRpc3RyaWJ1dGlvbiB1bmRlciAkSF8wJC4NCg0KDQpJbiBSLCB3ZSBvbmx5IG5lZWQgdG8gcHJvdmlkZSB0aGUgdmFsdWUgb2YgdGhlIG5vbi1jZW50cmFsaXR5IHBhcmFtZXRlciBgbmNwYCBmb3IgZmluZCB0aGUgdGFpbCBhcmVhcyBhbmQgb3RoZXIgcmVsYXRlZCB2YWx1ZXMgYXMgd2VsbC4NCg0KYGBge3IgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iNTAlIn0NCmluY2x1ZGVfZ3JhcGhpY3MoIk5vbmNlbnRyYWwudC5kaXN0cmlidXRpb24ucG5nIikNCmBgYA0KDQoNClRoZSBmb3JtdWxhIGZvciBzYW1wbGUgc2l6ZSBkZXRlcm1pbmF0aW9uIGlzIGEgcmVjdXJzaXZlIGVxdWF0aW9uIHdoaWNoIGlzIG5vdCBlYXN5IHRvIHVzZSBpbiBtYW51YWwgY2FsY3VsYXRpb24uIFdlIGNhbiBhcHByb3hpbWF0ZSB1c2luZyB6LXNjb3JlcyBpbiB0aGUgZm9sbG93aW5nDQoNCiQkDQpuIFxhcHByb3hcbGVmdCggXGZyYWN7KHpfezEtXGFscGhhLzJ9IC0gel97MS1cYmV0YX0pXHNpZ21hfXtcZGVsdGF9XHJpZ2h0KV4yLg0KJCQNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoqKlBvd2VyIENhbGN1bGF0aW9uIGluIE51bWVyaWNhbCBFeGFtcGxlKiogdXNpbmcgUiBmdW5jdGlvbiBgcG93ZXIudC50ZXN0KClgIGFuZCBtYW51YWwgY2FsY3VsYXRpb24gcmVzcGVjdGl2ZWx5Lg0KDQpDb25zaWRlciB0aGUgZm9sbG93aW5nIG9uZS1zYW1wbGUgdHdvLXRhaWxlZCB0ZXN0OiANCg0KJCQNCkhfMDogXG11ID0gMTAwLCBccXF1YWQgSF8xOiBcbXUgXG5lcSAxMDAgXHF1YWQgKFx0ZXh0e2UuZy59IFxxdWFkIFxtdSA9IDEwNilccXVhZCAoXHRleHR7dHdvLXNpZGVkfSkNCiQkDQoNCmFuZCB0aGUgZm9sbG93aW5nIGdpdmVuIGluZm9ybWF0aW9uDQoNCiQkDQpuID0gMjUsIFxhbHBoYSA9IDAuMDUsIFxzaWdtYSA9IDE1LCBcdGV4dHsgdHdvLXRhaWxlZCB0ZXN0fQ0KJCQNCg0KDQokJA0KXGxhbWJkYT0gXGZyYWN7MTA2IC0gMTAwfXsxNS9cc3FydHsyNX19ID0gXGZyYWN7Nn17M30gPSAyIFxxdWFkIFx0ZXh0eyBhbmQgfSBccXVhZCBcZGVsdGEgPSAxMDYtMTAwID0gNi4NCiQkDQoNClVzaW5nIHBvd2VyIHRhYmxlcyBvciBzb2Z0d2FyZTogUG93ZXIgJFxhcHByb3gkIDAuODANCg0KDQoNCg0KKipQb3dlciBDYWxjdWxhdGlvbiBVc2luZyBSKioNCg0KYGBge3J9DQojIFBvd2VyIGNhbGN1bGF0aW9uIGZvciBvbmUtc2FtcGxlIHQtdGVzdA0KcG93ZXJfY2FsYyA8LSBwb3dlci50LnRlc3QobiA9IDI1LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsdGEgPSA2LCAgICAjIHRydWUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBtZWFucyBpbiBIMCBhbmQgSGENCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2QgPSAxNSwgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2lnLmxldmVsID0gMC4wNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICJvbmUuc2FtcGxlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikNCnByaW50KHBvd2VyX2NhbGMpDQoNCiMgU2FtcGxlIHNpemUgY2FsY3VsYXRpb24NCnNhbXBsZV9zaXplIDwtIHBvd2VyLnQudGVzdChwb3dlciA9IDAuOTAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbHRhID0gNiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkID0gMTUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBzaWcubGV2ZWwgPSAwLjA1LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICJvbmUuc2FtcGxlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpDQpjYXQoIlxuUmVxdWlyZWQgc2FtcGxlIHNpemUgZm9yIDkwJSBwb3dlcjoiLCBjZWlsaW5nKHNhbXBsZV9zaXplJG4pKQ0KYGBgDQoNCg0KKipNYW51YWwgQ2FsY3VsYXRpb24qKiAtIHVzaW5nIFIgYXMgYSBjYWxjdWxhdG9yIGFuZCB0aGUgYmFzZSB0IGFuZCBaIGRpc3RyaWJ1dGlvbnMgaW4gYmFzZSBSIGxpYnJhcnkuDQoNCmBgYHtyfQ0KIyBnaXZlbiBpbmZvDQpuID0gMjUNCnBvd2VyID0gMC45MA0Kc2lnID0gMTUNCmRlbHRhID0gNg0KbGFtYmRhID0gMg0Kc2lnLmxldmVsID0gMC4wNQ0KIyMNCmNyaXQgPSBxdCgwLjk3NSwgbi0xKQ0KIyMNCnBvd2VyID0gMS1wdChjcml0LCBkZiA9IDI0LCBuY3AgPSBsYW1iZGEpICsgcHQoLWNyaXQsIGRmID0gMjQsIG5jcCA9IGxhbWJkYSkNCm4gPSgocW5vcm0oMC45NzUpLXFub3JtKDAuMTApKSpzaWcvZGVsdGEpXjIgDQpkYXRhLmZyYW1lKGNiaW5kKHBvd2VyID0gcG93ZXIsIG4gPSBuKSkNCmBgYA0KDQoNCk1hbnVhbCBjYWxjdWxhdGlvbiBhbmQgYHBvd2VyLnQudGVzdCgpYCB5aWVsZCB0aGUgc2FtZSByZXN1bHRzLCBidXQgbWFudWFsIGNhbGN1bGF0aW9uIHJlc3VsdHMgaW4gYSByZWxhdGl2ZWx5IGNvbnNlcnZhdGl2ZSBzYW1wbGUgc2l6ZS4NCg0K